add six.raise_from() to preserve exception traceback (#28532)
* add six.raise_from() to preserve exception traceback * add tests for code coverage
This commit is contained in:
parent
282fd57114
commit
645b40b249
@ -39,6 +39,7 @@
|
|||||||
from typing import List # novm
|
from typing import List # novm
|
||||||
|
|
||||||
import ruamel.yaml as yaml
|
import ruamel.yaml as yaml
|
||||||
|
import six
|
||||||
from ruamel.yaml.error import MarkedYAMLError
|
from ruamel.yaml.error import MarkedYAMLError
|
||||||
from six import iteritems
|
from six import iteritems
|
||||||
|
|
||||||
@ -975,7 +976,7 @@ def validate(data, schema, filename=None):
|
|||||||
line_number = e.instance.lc.line + 1
|
line_number = e.instance.lc.line + 1
|
||||||
else:
|
else:
|
||||||
line_number = None
|
line_number = None
|
||||||
raise ConfigFormatError(e, data, filename, line_number)
|
raise six.raise_from(ConfigFormatError(e, data, filename, line_number), e)
|
||||||
# return the validated data so that we can access the raw data
|
# return the validated data so that we can access the raw data
|
||||||
# mostly relevant for environments
|
# mostly relevant for environments
|
||||||
return test_data
|
return test_data
|
||||||
|
@ -734,7 +734,10 @@ def _read_from_file(self, filename):
|
|||||||
with open(filename, 'r') as f:
|
with open(filename, 'r') as f:
|
||||||
fdata = sjson.load(f)
|
fdata = sjson.load(f)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise CorruptDatabaseError("error parsing database:", str(e))
|
raise six.raise_from(
|
||||||
|
CorruptDatabaseError("error parsing database:", str(e)),
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
|
||||||
if fdata is None:
|
if fdata is None:
|
||||||
return
|
return
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
import ruamel.yaml as yaml
|
import ruamel.yaml as yaml
|
||||||
|
import six
|
||||||
|
|
||||||
import llnl.util.filesystem as fs
|
import llnl.util.filesystem as fs
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
@ -344,13 +345,13 @@ def remove_install_directory(self, spec, deprecated=False):
|
|||||||
os.unlink(path)
|
os.unlink(path)
|
||||||
os.remove(metapath)
|
os.remove(metapath)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
raise RemoveFailedError(spec, path, e)
|
raise six.raise_from(RemoveFailedError(spec, path, e), e)
|
||||||
|
|
||||||
elif os.path.exists(path):
|
elif os.path.exists(path):
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(path)
|
shutil.rmtree(path)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
raise RemoveFailedError(spec, path, e)
|
raise six.raise_from(RemoveFailedError(spec, path, e), e)
|
||||||
|
|
||||||
path = os.path.dirname(path)
|
path = os.path.dirname(path)
|
||||||
while path != self.root:
|
while path != self.root:
|
||||||
|
@ -9,8 +9,9 @@
|
|||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
import llnl.util.filesystem as fs
|
import llnl.util.filesystem as fs
|
||||||
import llnl.util.tty as tty
|
|
||||||
|
|
||||||
import spack.error
|
import spack.error
|
||||||
import spack.paths
|
import spack.paths
|
||||||
@ -292,8 +293,10 @@ def from_file(filename):
|
|||||||
test_suite._hash = content_hash
|
test_suite._hash = content_hash
|
||||||
return test_suite
|
return test_suite
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
tty.debug(e)
|
raise six.raise_from(
|
||||||
raise sjson.SpackJSONError("error parsing JSON TestSuite:", str(e))
|
sjson.SpackJSONError("error parsing JSON TestSuite:", str(e)),
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _add_msg_to_file(filename, msg):
|
def _add_msg_to_file(filename, msg):
|
||||||
|
@ -69,6 +69,10 @@ def __init__(self, fetch_url, push_url=None,
|
|||||||
self._push_url = push_url
|
self._push_url = push_url
|
||||||
self._name = name
|
self._name = name
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return (self._fetch_url == other._fetch_url and
|
||||||
|
self._push_url == other._push_url)
|
||||||
|
|
||||||
def to_json(self, stream=None):
|
def to_json(self, stream=None):
|
||||||
return sjson.dump(self.to_dict(), stream)
|
return sjson.dump(self.to_dict(), stream)
|
||||||
|
|
||||||
@ -81,12 +85,21 @@ def from_yaml(stream, name=None):
|
|||||||
data = syaml.load(stream)
|
data = syaml.load(stream)
|
||||||
return Mirror.from_dict(data, name)
|
return Mirror.from_dict(data, name)
|
||||||
except yaml_error.MarkedYAMLError as e:
|
except yaml_error.MarkedYAMLError as e:
|
||||||
raise syaml.SpackYAMLError("error parsing YAML spec:", str(e))
|
raise six.raise_from(
|
||||||
|
syaml.SpackYAMLError("error parsing YAML mirror:", str(e)),
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(stream, name=None):
|
def from_json(stream, name=None):
|
||||||
d = sjson.load(stream)
|
try:
|
||||||
return Mirror.from_dict(d, name)
|
d = sjson.load(stream)
|
||||||
|
return Mirror.from_dict(d, name)
|
||||||
|
except Exception as e:
|
||||||
|
raise six.raise_from(
|
||||||
|
sjson.SpackJSONError("error parsing JSON mirror:", str(e)),
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
if self._push_url is None:
|
if self._push_url is None:
|
||||||
@ -238,6 +251,9 @@ def __init__(self, mirrors=None, scope=None):
|
|||||||
mirrors.items() if mirrors is not None else
|
mirrors.items() if mirrors is not None else
|
||||||
spack.config.get('mirrors', scope=scope).items()))
|
spack.config.get('mirrors', scope=scope).items()))
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self._mirrors == other._mirrors
|
||||||
|
|
||||||
def to_json(self, stream=None):
|
def to_json(self, stream=None):
|
||||||
return sjson.dump(self.to_dict(True), stream)
|
return sjson.dump(self.to_dict(True), stream)
|
||||||
|
|
||||||
@ -251,12 +267,21 @@ def from_yaml(stream, name=None):
|
|||||||
data = syaml.load(stream)
|
data = syaml.load(stream)
|
||||||
return MirrorCollection(data)
|
return MirrorCollection(data)
|
||||||
except yaml_error.MarkedYAMLError as e:
|
except yaml_error.MarkedYAMLError as e:
|
||||||
raise syaml.SpackYAMLError("error parsing YAML spec:", str(e))
|
raise six.raise_from(
|
||||||
|
syaml.SpackYAMLError("error parsing YAML mirror collection:", str(e)),
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(stream, name=None):
|
def from_json(stream, name=None):
|
||||||
d = sjson.load(stream)
|
try:
|
||||||
return MirrorCollection(d)
|
d = sjson.load(stream)
|
||||||
|
return MirrorCollection(d)
|
||||||
|
except Exception as e:
|
||||||
|
raise six.raise_from(
|
||||||
|
sjson.SpackJSONError("error parsing JSON mirror collection:", str(e)),
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
|
||||||
def to_dict(self, recursive=False):
|
def to_dict(self, recursive=False):
|
||||||
return syaml_dict(sorted(
|
return syaml_dict(sorted(
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
from io import BufferedReader
|
from io import BufferedReader
|
||||||
|
|
||||||
|
import six
|
||||||
import six.moves.urllib.error as urllib_error
|
import six.moves.urllib.error as urllib_error
|
||||||
import six.moves.urllib.request as urllib_request
|
import six.moves.urllib.request as urllib_request
|
||||||
import six.moves.urllib.response as urllib_response
|
import six.moves.urllib.response as urllib_response
|
||||||
@ -79,11 +80,11 @@ def s3_open(self, req):
|
|||||||
except ClientError as err2:
|
except ClientError as err2:
|
||||||
if err.response['Error']['Code'] == 'NoSuchKey':
|
if err.response['Error']['Code'] == 'NoSuchKey':
|
||||||
# raise original error
|
# raise original error
|
||||||
raise urllib_error.URLError(err)
|
raise six.raise_from(urllib_error.URLError(err), err)
|
||||||
|
|
||||||
raise urllib_error.URLError(err2)
|
raise six.raise_from(urllib_error.URLError(err2), err2)
|
||||||
|
|
||||||
raise urllib_error.URLError(err)
|
raise six.raise_from(urllib_error.URLError(err), err)
|
||||||
|
|
||||||
|
|
||||||
S3OpenerDirector = urllib_request.build_opener(UrllibS3Handler())
|
S3OpenerDirector = urllib_request.build_opener(UrllibS3Handler())
|
||||||
|
@ -2183,7 +2183,10 @@ def from_yaml(stream):
|
|||||||
data = yaml.load(stream)
|
data = yaml.load(stream)
|
||||||
return Spec.from_dict(data)
|
return Spec.from_dict(data)
|
||||||
except yaml.error.MarkedYAMLError as e:
|
except yaml.error.MarkedYAMLError as e:
|
||||||
raise syaml.SpackYAMLError("error parsing YAML spec:", str(e))
|
raise six.raise_from(
|
||||||
|
syaml.SpackYAMLError("error parsing YAML spec:", str(e)),
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(stream):
|
def from_json(stream):
|
||||||
@ -2196,8 +2199,10 @@ def from_json(stream):
|
|||||||
data = sjson.load(stream)
|
data = sjson.load(stream)
|
||||||
return Spec.from_dict(data)
|
return Spec.from_dict(data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
tty.debug(e)
|
raise six.raise_from(
|
||||||
raise sjson.SpackJSONError("error parsing JSON spec:", str(e))
|
sjson.SpackJSONError("error parsing JSON spec:", str(e)),
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_detection(spec_str, extra_attributes=None):
|
def from_detection(spec_str, extra_attributes=None):
|
||||||
@ -2734,7 +2739,10 @@ def flat_dependencies(self, **kwargs):
|
|||||||
# with inconsistent constraints. Users cannot produce
|
# with inconsistent constraints. Users cannot produce
|
||||||
# inconsistent specs like this on the command line: the
|
# inconsistent specs like this on the command line: the
|
||||||
# parser doesn't allow it. Spack must be broken!
|
# parser doesn't allow it. Spack must be broken!
|
||||||
raise InconsistentSpecError("Invalid Spec DAG: %s" % e.message)
|
raise six.raise_from(
|
||||||
|
InconsistentSpecError("Invalid Spec DAG: %s" % e.message),
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
|
||||||
def index(self, deptype='all'):
|
def index(self, deptype='all'):
|
||||||
"""Return DependencyMap that points to all the dependencies in this
|
"""Return DependencyMap that points to all the dependencies in this
|
||||||
@ -4767,7 +4775,7 @@ def do_parse(self):
|
|||||||
self.unexpected_token()
|
self.unexpected_token()
|
||||||
|
|
||||||
except spack.parse.ParseError as e:
|
except spack.parse.ParseError as e:
|
||||||
raise SpecParseError(e)
|
raise six.raise_from(SpecParseError(e), e)
|
||||||
|
|
||||||
# Generate lookups for git-commit-based versions
|
# Generate lookups for git-commit-based versions
|
||||||
for spec in specs:
|
for spec in specs:
|
||||||
|
@ -365,6 +365,31 @@ def __call__(self, *args, **kwargs):
|
|||||||
assert('Unable to merge {0}'.format(c1) in err)
|
assert('Unable to merge {0}'.format(c1) in err)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"obj, proto",
|
||||||
|
[
|
||||||
|
({}, []),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_ci_opt_argument_checking(obj, proto):
|
||||||
|
"""Check that matches() and subkeys() return False when `proto` is not a dict."""
|
||||||
|
assert not ci_opt.matches(obj, proto)
|
||||||
|
assert not ci_opt.subkeys(obj, proto)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"yaml",
|
||||||
|
[
|
||||||
|
{'extends': 1},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_ci_opt_add_extends_non_sequence(yaml):
|
||||||
|
"""Check that add_extends() exits if 'extends' is not a sequence."""
|
||||||
|
yaml_copy = yaml.copy()
|
||||||
|
ci_opt.add_extends(yaml, None)
|
||||||
|
assert yaml == yaml_copy
|
||||||
|
|
||||||
|
|
||||||
def test_ci_workarounds():
|
def test_ci_workarounds():
|
||||||
fake_root_spec = 'x' * 544
|
fake_root_spec = 'x' * 544
|
||||||
fake_spack_ref = 'x' * 40
|
fake_spack_ref = 'x' * 40
|
||||||
|
@ -13,9 +13,11 @@
|
|||||||
import spack.mirror
|
import spack.mirror
|
||||||
import spack.repo
|
import spack.repo
|
||||||
import spack.util.executable
|
import spack.util.executable
|
||||||
|
import spack.util.spack_json as sjson
|
||||||
from spack.spec import Spec
|
from spack.spec import Spec
|
||||||
from spack.stage import Stage
|
from spack.stage import Stage
|
||||||
from spack.util.executable import which
|
from spack.util.executable import which
|
||||||
|
from spack.util.spack_yaml import SpackYAMLError
|
||||||
|
|
||||||
pytestmark = pytest.mark.usefixtures('mutable_config', 'mutable_mock_repo')
|
pytestmark = pytest.mark.usefixtures('mutable_config', 'mutable_mock_repo')
|
||||||
|
|
||||||
@ -149,6 +151,100 @@ def test_all_mirror(
|
|||||||
repos.clear()
|
repos.clear()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"mirror",
|
||||||
|
[
|
||||||
|
spack.mirror.Mirror(
|
||||||
|
'https://example.com/fetch',
|
||||||
|
'https://example.com/push',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_roundtrip_mirror(mirror):
|
||||||
|
mirror_yaml = mirror.to_yaml()
|
||||||
|
assert spack.mirror.Mirror.from_yaml(mirror_yaml) == mirror
|
||||||
|
mirror_json = mirror.to_json()
|
||||||
|
assert spack.mirror.Mirror.from_json(mirror_json) == mirror
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"invalid_yaml",
|
||||||
|
[
|
||||||
|
"playing_playlist: {{ action }} playlist {{ playlist_name }}"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
def test_invalid_yaml_mirror(invalid_yaml):
|
||||||
|
with pytest.raises(SpackYAMLError) as e:
|
||||||
|
spack.mirror.Mirror.from_yaml(invalid_yaml)
|
||||||
|
exc_msg = str(e.value)
|
||||||
|
assert exc_msg.startswith("error parsing YAML mirror:")
|
||||||
|
assert invalid_yaml in exc_msg
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"invalid_json, error_message",
|
||||||
|
[
|
||||||
|
("{13:", "Expecting property name")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
def test_invalid_json_mirror(invalid_json, error_message):
|
||||||
|
with pytest.raises(sjson.SpackJSONError) as e:
|
||||||
|
spack.mirror.Mirror.from_json(invalid_json)
|
||||||
|
exc_msg = str(e.value)
|
||||||
|
assert exc_msg.startswith("error parsing JSON mirror:")
|
||||||
|
assert error_message in exc_msg
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"mirror_collection",
|
||||||
|
[
|
||||||
|
spack.mirror.MirrorCollection(
|
||||||
|
mirrors={
|
||||||
|
'example-mirror': spack.mirror.Mirror(
|
||||||
|
'https://example.com/fetch',
|
||||||
|
'https://example.com/push',
|
||||||
|
).to_dict(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_roundtrip_mirror_collection(mirror_collection):
|
||||||
|
mirror_collection_yaml = mirror_collection.to_yaml()
|
||||||
|
assert (spack.mirror.MirrorCollection.from_yaml(mirror_collection_yaml) ==
|
||||||
|
mirror_collection)
|
||||||
|
mirror_collection_json = mirror_collection.to_json()
|
||||||
|
assert (spack.mirror.MirrorCollection.from_json(mirror_collection_json) ==
|
||||||
|
mirror_collection)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"invalid_yaml",
|
||||||
|
[
|
||||||
|
"playing_playlist: {{ action }} playlist {{ playlist_name }}"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
def test_invalid_yaml_mirror_collection(invalid_yaml):
|
||||||
|
with pytest.raises(SpackYAMLError) as e:
|
||||||
|
spack.mirror.MirrorCollection.from_yaml(invalid_yaml)
|
||||||
|
exc_msg = str(e.value)
|
||||||
|
assert exc_msg.startswith("error parsing YAML mirror collection:")
|
||||||
|
assert invalid_yaml in exc_msg
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"invalid_json, error_message",
|
||||||
|
[
|
||||||
|
("{13:", "Expecting property name")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
def test_invalid_json_mirror_collection(invalid_json, error_message):
|
||||||
|
with pytest.raises(sjson.SpackJSONError) as e:
|
||||||
|
spack.mirror.MirrorCollection.from_json(invalid_json)
|
||||||
|
exc_msg = str(e.value)
|
||||||
|
assert exc_msg.startswith("error parsing JSON mirror collection:")
|
||||||
|
assert error_message in exc_msg
|
||||||
|
|
||||||
|
|
||||||
def test_mirror_archive_paths_no_version(mock_packages, config, mock_archive):
|
def test_mirror_archive_paths_no_version(mock_packages, config, mock_archive):
|
||||||
spec = Spec('trivial-install-test-package@nonexistingversion')
|
spec = Spec('trivial-install-test-package@nonexistingversion')
|
||||||
fetcher = spack.fetch_strategy.URLFetchStrategy(mock_archive.url)
|
fetcher = spack.fetch_strategy.URLFetchStrategy(mock_archive.url)
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
from spack import repo
|
from spack import repo
|
||||||
from spack.spec import Spec, save_dependency_specfiles
|
from spack.spec import Spec, save_dependency_specfiles
|
||||||
from spack.util.mock_package import MockPackageMultiRepo
|
from spack.util.mock_package import MockPackageMultiRepo
|
||||||
from spack.util.spack_yaml import syaml_dict
|
from spack.util.spack_yaml import SpackYAMLError, syaml_dict
|
||||||
|
|
||||||
if sys.version_info >= (3, 3):
|
if sys.version_info >= (3, 3):
|
||||||
from collections.abc import Iterable, Mapping # novm
|
from collections.abc import Iterable, Mapping # novm
|
||||||
@ -56,6 +56,34 @@ def test_normal_spec(mock_packages):
|
|||||||
check_json_round_trip(spec)
|
check_json_round_trip(spec)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"invalid_yaml",
|
||||||
|
[
|
||||||
|
"playing_playlist: {{ action }} playlist {{ playlist_name }}"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
def test_invalid_yaml_spec(invalid_yaml):
|
||||||
|
with pytest.raises(SpackYAMLError) as e:
|
||||||
|
Spec.from_yaml(invalid_yaml)
|
||||||
|
exc_msg = str(e.value)
|
||||||
|
assert exc_msg.startswith("error parsing YAML spec:")
|
||||||
|
assert invalid_yaml in exc_msg
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"invalid_json, error_message",
|
||||||
|
[
|
||||||
|
("{13:", "Expecting property name")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
def test_invalid_json_spec(invalid_json, error_message):
|
||||||
|
with pytest.raises(sjson.SpackJSONError) as e:
|
||||||
|
Spec.from_json(invalid_json)
|
||||||
|
exc_msg = str(e.value)
|
||||||
|
assert exc_msg.startswith("error parsing JSON spec:")
|
||||||
|
assert error_message in exc_msg
|
||||||
|
|
||||||
|
|
||||||
def test_external_spec(config, mock_packages):
|
def test_external_spec(config, mock_packages):
|
||||||
spec = Spec('externaltool')
|
spec = Spec('externaltool')
|
||||||
spec.concretize()
|
spec.concretize()
|
||||||
|
Loading…
Reference in New Issue
Block a user