Skip to content
Snippets Groups Projects
Verified Commit d54c31cd authored by Daniel Hornung's avatar Daniel Hornung
Browse files

ENH: Also hande the case where spss is not installed.

parent c0c2ea17
No related branches found
No related tags found
2 merge requests!178FIX: #96 Better error output for crawl.py script.,!171sav/spss converter
Pipeline #52187 passed
from . import converters
from .conv_impl.spss import SPSSConverter
from . import converters, utils
try:
from .conv_impl.spss import SPSSConverter
except ImportError as err:
SPSSConverter: type = utils.MissingImport(
name="SPSSConverter", hint="Try installing with the `spss` extra option.",
err=err)
from .crawl import Crawler, SecurityMode
from .version import CfoodRequiredVersionError, get_caoscrawler_version
......
......@@ -25,6 +25,9 @@
# Some utility functions, e.g. for extending pylib.
import sys
from typing import Optional
import linkahead as db
......@@ -39,3 +42,30 @@ def has_parent(entity: db.Entity, name: str):
if parent.name == name:
return True
return False
def MissingImport(name: str, hint: str = "", err: Optional[Exception] = None) -> type:
"""Factory with dummy classes, which may be assigned to variables but never used."""
def _error():
error_msg = f"This class ({name}) cannot be used, because some libraries are missing."
if hint:
error_msg += "\n\n" + hint
if err:
print(error_msg, file=sys.stdout)
raise RuntimeError(error_msg) from err
raise RuntimeError(error_msg)
class _Meta(type):
def __getattribute__(cls, *args, **kwargs):
_error()
def __call__(cls, *args, **kwargs):
_error()
class _DummyClass(metaclass=_Meta):
pass
_DummyClass.__name__ = name
return _DummyClass
......@@ -19,7 +19,10 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
import pytest
from caoscrawler.crawl import split_restricted_path
from caoscrawler.utils import MissingImport
def test_split_restricted_path():
......@@ -33,3 +36,33 @@ def test_split_restricted_path():
assert split_restricted_path("/test//bla") == ["test", "bla"]
assert split_restricted_path("//test/bla") == ["test", "bla"]
assert split_restricted_path("///test//bla////") == ["test", "bla"]
def test_dummy_class():
Missing = MissingImport(name="Not Important", hint="Do the thing instead.")
with pytest.raises(RuntimeError) as err_info_1:
print(Missing.__name__)
with pytest.raises(RuntimeError) as err_info_2:
Missing()
with pytest.raises(RuntimeError) as err_info_3:
print(Missing.foo)
for err_info in (err_info_1, err_info_2, err_info_3):
msg = str(err_info.value)
assert "(Not Important)" in msg
assert msg.endswith("Do the thing instead.")
MissingErr = MissingImport(name="Not Important", hint="Do the thing instead.",
err=ImportError("Old error"))
with pytest.raises(RuntimeError) as err_info_1:
print(MissingErr.__name__)
with pytest.raises(RuntimeError) as err_info_2:
MissingErr()
with pytest.raises(RuntimeError) as err_info_3:
print(MissingErr.foo)
for err_info in (err_info_1, err_info_2, err_info_3):
msg = str(err_info.value)
assert "(Not Important)" in msg
orig_msg = str(err_info.value.__cause__)
assert orig_msg == "Old error"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment