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

Implement exceptions in Python and allow to retrieve meaningful information #162

Merged
merged 6 commits into from
Jul 5, 2023
Merged
Show file tree
Hide file tree
Changes from 3 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
14 changes: 8 additions & 6 deletions py/kiwisolver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,23 @@
# The full license is in the file LICENSE, distributed with this software.
# --------------------------------------------------------------------------------------
from ._cext import (
BadRequiredStrength,
Constraint,
DuplicateConstraint,
DuplicateEditVariable,
Expression,
Solver,
Term,
UnknownConstraint,
UnknownEditVariable,
UnsatisfiableConstraint,
Variable,
__kiwi_version__,
__version__,
strength,
)
from .exceptions import (
BadRequiredStrength,
DuplicateConstraint,
DuplicateEditVariable,
UnknownConstraint,
UnknownEditVariable,
UnsatisfiableConstraint,
)

__all__ = [
"BadRequiredStrength",
Expand Down
9 changes: 0 additions & 9 deletions py/kiwisolver/_cext.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,6 @@ except ImportError:
__version__: str
__kiwi_version__: str

# --- Exceptions

class BadRequiredStrength(Exception): ...
class DuplicateConstraint(Exception): ...
class DuplicateEditVariable(Exception): ...
class UnknownConstraint(Exception): ...
class UnknownEditVariable(Exception): ...
class UnsatisfiableConstraint(Exception): ...

# Types
@type_check_only
class Strength:
Expand Down
47 changes: 47 additions & 0 deletions py/kiwisolver/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# --------------------------------------------------------------------------------------
# Copyright (c) 2023, Nucleic Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file LICENSE, distributed with this software.
# --------------------------------------------------------------------------------------
"""Kiwi exceptions."""

MatthieuDartiailh marked this conversation as resolved.
Show resolved Hide resolved

class BadRequiredStrength(Exception):
pass


class DuplicateConstraint(Exception):
__slots__ = ("constraint",)

def __init__(self, constraint):
self.constraint = constraint


class DuplicateEditVariable(Exception):
__slots__ = ("edit_variable",)

def __init__(self, edit_variable):
self.edit_variable = edit_variable


class UnknownConstraint(Exception):
__slots__ = ("constraint",)

def __init__(self, constraint):
self.constraint = constraint


class UnknownEditVariable(Exception):
__slots__ = ("edit_variable",)

def __init__(self, edit_variable):
self.edit_variable = edit_variable


class UnsatisfiableConstraint(Exception):
__slots__ = "constraint"
MatthieuDartiailh marked this conversation as resolved.
Show resolved Hide resolved

def __init__(self, constraint):
self.constraint = constraint
24 changes: 12 additions & 12 deletions py/src/solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,43 +290,43 @@ PyObject* BadRequiredStrength;

bool init_exceptions()
{
DuplicateConstraint = PyErr_NewException(
const_cast<char*>( "kiwisolver.DuplicateConstraint" ), 0, 0 );
cppy::ptr mod( PyImport_ImportModule( "kiwisolver.exceptions" ) );
if( !mod )
{
return false;
}

DuplicateConstraint = mod.getattr( "DuplicateConstraint" );
if( !DuplicateConstraint )
{
return false;
}

UnsatisfiableConstraint = PyErr_NewException(
const_cast<char*>( "kiwisolver.UnsatisfiableConstraint" ), 0, 0 );
UnsatisfiableConstraint = mod.getattr( "UnsatisfiableConstraint" );
if( !UnsatisfiableConstraint )
{
return false;
}

UnknownConstraint = PyErr_NewException(
const_cast<char*>( "kiwisolver.UnknownConstraint" ), 0, 0 );
UnknownConstraint = mod.getattr( "UnknownConstraint" );
if( !UnknownConstraint )
{
return false;
}

DuplicateEditVariable = PyErr_NewException(
const_cast<char*>( "kiwisolver.DuplicateEditVariable" ), 0, 0 );
DuplicateEditVariable = mod.getattr( "DuplicateEditVariable" );
if( !DuplicateEditVariable )
{
return false;
}

UnknownEditVariable = PyErr_NewException(
const_cast<char*>( "kiwisolver.UnknownEditVariable" ), 0, 0 );
UnknownEditVariable = mod.getattr( "UnknownEditVariable" );
if( !UnknownEditVariable )
{
return false;
}

BadRequiredStrength = PyErr_NewException(
const_cast<char*>( "kiwisolver.BadRequiredStrength" ), 0, 0 );
BadRequiredStrength = mod.getattr( "BadRequiredStrength" );
if( !BadRequiredStrength )
{
return false;
Expand Down
18 changes: 12 additions & 6 deletions py/tests/test_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@ def test_managing_edit_variable() -> None:
assert not s.hasEditVariable(v1)
s.addEditVariable(v1, "weak")
assert s.hasEditVariable(v1)
with pytest.raises(DuplicateEditVariable):
with pytest.raises(DuplicateEditVariable) as e:
s.addEditVariable(v1, "medium")
with pytest.raises(UnknownEditVariable):
assert e.value.edit_variable is v1
MatthieuDartiailh marked this conversation as resolved.
Show resolved Hide resolved
with pytest.raises(UnknownEditVariable) as e:
s.removeEditVariable(v2)
assert e.value.edit_variable is v2
s.removeEditVariable(v1)
assert not s.hasEditVariable(v1)

Expand All @@ -58,8 +60,9 @@ def test_managing_edit_variable() -> None:

s.addEditVariable(v2, "strong")
assert s.hasEditVariable(v2)
with pytest.raises(UnknownEditVariable):
with pytest.raises(UnknownEditVariable) as e:
s.suggestValue(v1, 10)
assert e.value.edit_variable is v1

s.reset()
assert not s.hasEditVariable(v2)
Expand Down Expand Up @@ -109,12 +112,15 @@ def test_managing_constraints() -> None:
assert not s.hasConstraint(c1)
s.addConstraint(c1)
assert s.hasConstraint(c1)
with pytest.raises(DuplicateConstraint):
with pytest.raises(DuplicateConstraint) as e:
s.addConstraint(c1)
with pytest.raises(UnknownConstraint):
assert e.value.constraint is c1
with pytest.raises(UnknownConstraint) as e:
s.removeConstraint(c2)
with pytest.raises(UnsatisfiableConstraint):
assert e.value.constraint is c2
with pytest.raises(UnsatisfiableConstraint) as e:
s.addConstraint(c2)
assert e.value.constraint is c2
# XXX need to find how to get an invalid symbol from choose subject
# with pytest.raises(UnsatisfiableConstraint):
# s.addConstraint(c3)
Expand Down