Skip to content

Commit

Permalink
add comparable_with methods for Holding
Browse files Browse the repository at this point in the history
  • Loading branch information
mscarey committed Apr 7, 2021
1 parent 2ec532d commit cac2724
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 26 deletions.
44 changes: 23 additions & 21 deletions authorityspoke/holdings.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
ContextRegister,
Explanation,
FactorMatch,
Term,
TermSequence,
contradicts,
new_context_helper,
Expand Down Expand Up @@ -287,7 +288,8 @@ def explanations_contradiction(
a generator yielding :class:`.ContextRegister`\s that cause a
contradiction.
"""

if not self.comparable_with(other):
raise TypeError(f"Type Holding cannot be compared with type {type(other)}.")
if not isinstance(context, Explanation):
context = Explanation.from_context(context)
if isinstance(other, Procedure):
Expand All @@ -296,17 +298,10 @@ def explanations_contradiction(
other = Holding(rule=other)
if isinstance(other, self.__class__):
yield from self._explanations_contradiction_of_holding(other, context)
elif isinstance(other, Factor): # other is a Factor
yield from [] # no possible contradiction
elif hasattr(other, "explanations_contradiction"):
else:
yield from other.explanations_contradiction(
self, context=context.reversed_context()
)
else:
raise TypeError(
f"'Contradicts' test not implemented for types "
f"{self.__class__} and {other.__class__}."
)

def _contradicts_if_not_exclusive(
self, other: Holding, context: Explanation
Expand All @@ -325,8 +320,6 @@ def _contradicts_if_not_exclusive(
def _explanations_implies_if_not_exclusive(
self, other: Factor, context: Explanation
) -> Iterator[Explanation]:
if not isinstance(other, self.__class__):
raise TypeError

if self.decided and other.decided:
yield from self._implies_if_decided(other, context)
Expand All @@ -347,6 +340,12 @@ def _explanations_implies_if_not_exclusive(
def __ge__(self, other: Optional[Factor]) -> bool:
return self.implies(other)

def comparable_with(self, other: Any) -> bool:
"""Check if other can be compared to self for implication or contradiction."""
if other and not isinstance(other, Comparable):
return False
return not isinstance(other, Factor)

def implies(
self, other: Optional[Comparable], context: ContextRegister = None
) -> bool:
Expand All @@ -367,26 +366,29 @@ def implies(
"""
if other is None:
return True
if isinstance(other, (Rule, Procedure)):
other = Holding(rule=other)
if not isinstance(other, self.__class__):
if hasattr(other, "implied_by"):
if context:
context = context.reversed()
return other.implied_by(self, context=context)
return False
return any(
explanation is not None
for explanation in self.explanations_implication(other, context)
)

def explanations_implication(
self, other: Holding, context: Optional[ContextRegister] = None
self,
other: Comparable,
context: Optional[Union[ContextRegister, Explanation]] = None,
) -> Iterator[ContextRegister]:
"""Yield contexts that would cause self and other to have same meaning."""
if not self.comparable_with(other):
raise TypeError(f"Type Holding cannot be compared with type {type(other)}.")
if not isinstance(context, Explanation):
context = Explanation.from_context(context)
if self.exclusive is other.exclusive is False:
if isinstance(other, (Rule, Procedure)):
other = Holding(rule=other)
if not isinstance(other, self.__class__):
if context:
context = context.reversed_context()
if other.implied_by(self, context=context):
yield context
elif self.exclusive is other.exclusive is False:
yield from self._explanations_implies_if_not_exclusive(
other, context=context
)
Expand Down
19 changes: 14 additions & 5 deletions tests/test_holdings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from copy import deepcopy
import os
from typing import Type

import pytest

Expand Down Expand Up @@ -221,10 +222,7 @@ def test_holding_implies_opinion_with_no_holdings(
context.insert_pair(
Entity("the Java API"), Entity("the Lotus menu command hierarchy")
)
assert holding.implies(
lotus,
context=context,
)
assert holding.implies(lotus, context=context)

def test_holding_implies_none(self, make_holding):
assert make_holding["h3"] >= None
Expand Down Expand Up @@ -291,6 +289,14 @@ def test_not_implied_by_statement(self, make_holding):
Predicate("$person was a person"), terms=Entity("Alice")
).implies(make_holding["h1"])

def test_cannot_check_if_holding_implies_factor(self, make_holding, make_factor):
with pytest.raises(TypeError):
make_holding["h1"].implies(make_factor["f_no_crime"])

def test_cannot_check_if_holding_implies_string(self, make_holding):
with pytest.raises(TypeError):
make_holding["h1"].implies("f_no_crime")


class TestContradiction:
def test_holding_contradicts_invalid_version_of_self(self, make_holding):
Expand Down Expand Up @@ -425,8 +431,11 @@ def test_no_holding_contradiction_explanations(self, make_opinion_with_holding):
explanation = lotus.holdings[1].explain_contradiction(lotus.holdings[2])
assert explanation is None

def test_no_comparison_holding_to_fact(self, make_holding, watt_factor):
with pytest.raises(TypeError):
make_holding["h1"].contradicts(watt_factor["f1"])

def test_holding_does_not_contradict_fact(self, make_holding, watt_factor):
assert not make_holding["h1"].contradicts(watt_factor["f1"])
assert not watt_factor["f1"].contradicts(make_holding["h1"])

def test_error_no_contradiction_test(self, make_holding):
Expand Down

0 comments on commit cac2724

Please sign in to comment.