forked from ITISFoundation/osparc-simcore
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into buy-credits
Conflicts: services/static-webserver/client/source/class/osparc/desktop/credits/BuyCreditsStepper.js
- Loading branch information
Showing
41 changed files
with
510 additions
and
222 deletions.
There are no files selected for viewing
23 changes: 23 additions & 0 deletions
23
packages/models-library/src/models_library/errors_classes.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
from pydantic.errors import PydanticErrorMixin | ||
|
||
|
||
class OsparcErrorMixin(PydanticErrorMixin): | ||
def __new__(cls, *args, **kwargs): | ||
if not hasattr(cls, "code"): | ||
cls.code = cls._get_full_class_name() | ||
return super().__new__(cls, *args, **kwargs) | ||
|
||
@classmethod | ||
def _get_full_class_name(cls) -> str: | ||
relevant_classes = [ | ||
c.__name__ | ||
for c in cls.__mro__[:-1] | ||
if c.__name__ | ||
not in ( | ||
"PydanticErrorMixin", | ||
"OsparcErrorMixin", | ||
"Exception", | ||
"BaseException", | ||
) | ||
] | ||
return ".".join(reversed(relevant_classes)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
# pylint: disable=protected-access | ||
# pylint: disable=redefined-outer-name | ||
# pylint: disable=unused-argument | ||
# pylint: disable=unused-variable | ||
# pylint: disable=no-member | ||
|
||
|
||
from datetime import datetime | ||
from typing import Any | ||
|
||
import pytest | ||
from models_library.errors_classes import OsparcErrorMixin | ||
|
||
|
||
def test_get_full_class_name(): | ||
class A(OsparcErrorMixin): | ||
... | ||
|
||
class B1(A): | ||
... | ||
|
||
class B2(A): | ||
... | ||
|
||
class C(B2): | ||
... | ||
|
||
class B12(B1, ValueError): | ||
... | ||
|
||
assert B1._get_full_class_name() == "A.B1" | ||
assert C._get_full_class_name() == "A.B2.C" | ||
assert A._get_full_class_name() == "A" | ||
|
||
# diamond inheritance (not usual but supported) | ||
assert B12._get_full_class_name() == "ValueError.A.B1.B12" | ||
|
||
|
||
def test_error_codes_and_msg_template(): | ||
class MyBaseError(OsparcErrorMixin, Exception): | ||
def __init__(self, **ctx: Any) -> None: | ||
super().__init__(**ctx) # Do not forget this for base exceptions! | ||
|
||
class MyValueError(MyBaseError, ValueError): | ||
msg_template = "Wrong value {value}" | ||
|
||
error = MyValueError(value=42) | ||
|
||
assert error.code == "ValueError.MyBaseError.MyValueError" | ||
assert f"{error}" == "Wrong value 42" | ||
|
||
class MyTypeError(MyBaseError, TypeError): | ||
code = "i_want_this" | ||
msg_template = "Wrong type {type}" | ||
|
||
error = MyTypeError(type="int") | ||
|
||
assert error.code == "i_want_this" | ||
assert f"{error}" == "Wrong type int" | ||
|
||
|
||
def test_error_msg_template_override(): | ||
class MyError(OsparcErrorMixin, Exception): | ||
msg_template = "Wrong value {value}" | ||
|
||
error_override_msg = MyError(msg_template="I want this message") | ||
assert str(error_override_msg) == "I want this message" | ||
|
||
error = MyError(value=42) | ||
assert hasattr(error, "value") | ||
assert str(error) == f"Wrong value {error.value}" | ||
|
||
|
||
def test_error_msg_template_nicer_override(): | ||
class MyError(OsparcErrorMixin, Exception): | ||
msg_template = "Wrong value {value}" | ||
|
||
def __init__(self, msg=None, **ctx: Any) -> None: | ||
super().__init__(**ctx) | ||
# positional argument msg (if defined) overrides the msg_template | ||
if msg: | ||
self.msg_template = msg | ||
|
||
error_override_msg = MyError("I want this message") | ||
assert str(error_override_msg) == "I want this message" | ||
|
||
error = MyError(value=42) | ||
assert hasattr(error, "value") | ||
assert str(error) == f"Wrong value {error.value}" | ||
|
||
|
||
def test_error_with_constructor(): | ||
class MyError(OsparcErrorMixin, ValueError): | ||
msg_template = "Wrong value {value}" | ||
|
||
# handy e.g. autocompletion | ||
def __init__(self, *, my_value: int = 42, **extra): | ||
super().__init__(**extra) | ||
self.value = my_value | ||
|
||
error = MyError(my_value=33, something_else="yes") | ||
assert error.value == 33 | ||
assert str(error) == "Wrong value 33" | ||
assert not hasattr(error, "my_value") | ||
|
||
# the autocompletion does not see this | ||
assert error.something_else == "yes" | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"str_format,ctx,expected", | ||
[ | ||
pytest.param("{value:10}", {"value": "Python"}, "Python ", id="left-align"), | ||
pytest.param( | ||
"{value:>10}", {"value": "Python"}, " Python", id="right-align" | ||
), | ||
pytest.param( | ||
"{value:^10}", {"value": "Python"}, " Python ", id="center-align" | ||
), | ||
pytest.param("{v:.2f}", {"v": 3.1415926}, "3.14", id="decimals"), | ||
pytest.param( | ||
"{dt:%Y-%m-%d %H:%M}", | ||
{"dt": datetime(2020, 5, 17, 18, 45)}, | ||
"2020-05-17 18:45", | ||
id="datetime", | ||
), | ||
], | ||
) | ||
def test_msg_template_with_different_formats( | ||
str_format: str, ctx: dict[str, Any], expected: str | ||
): | ||
class MyError(OsparcErrorMixin, ValueError): | ||
msg_template = str_format | ||
|
||
error = MyError(**ctx) | ||
assert str(error) == expected |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.