From 42e1ebc4eb18dd10f2da226d26b7cc435d0a6efd Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Tue, 12 Oct 2021 12:56:04 +0200 Subject: [PATCH 001/154] [wip] harmonising types in tuprolog.core --- tuprolog/core/_ktadapt.py | 183 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) diff --git a/tuprolog/core/_ktadapt.py b/tuprolog/core/_ktadapt.py index f728a04..09f4142 100644 --- a/tuprolog/core/_ktadapt.py +++ b/tuprolog/core/_ktadapt.py @@ -2,6 +2,8 @@ import jpype +from tuprolog.pyutils import iterable_or_varargs + @jpype.JImplementationFor("it.unibo.tuprolog.core.Term") class _KtTerm: @@ -15,6 +17,107 @@ def __getitem__(self, item, *items): def variables(self): return self.getVariables() + def structurally_equals(self, other): + return self.structurallyEquals(other) + + @jpype.JOverride() + def equals(self, other, use_var_complete_name: bool = True): + return self.equals_(other, use_var_complete_name) + + @property + def is_var(self): + return self.isVar() + + @property + def is_ground(self): + return self.isGround() + + @property + def is_struct(self): + return self.isStruct() + + @property + def is_truth(self): + return self.isTruth() + + @property + def is_recursive(self): + return self.isRecursive() + + @property + def is_atom(self): + return self.isAtom() + + @property + def is_constant(self): + return self.isConstant() + + @property + def is_number(self): + return self.isNumber() + + @property + def is_integer(self): + return self.is_integer() + + @property + def is_real(self): + return self.isReal() + + @property + def is_list(self): + return self.isList() + + @property + def is_tuple(self): + return self.isTuple() + + @property + def is_block(self): + return self.isBlock() + + @property + def is_clause(self): + return self.isClause() + + @property + def is_rule(self): + return self.isRule() + + @property + def is_fact(self): + return self.isFact() + + @property + def is_directive(self): + return self.isDirective() + + @property + def is_cons(self): + return self.isCons() + + @property + def is_empty_list(self): + return self.isEmptyList() + + @property + def is_true(self): + return self.isTrue() + + @property + def is_fail(self): + return self.isFail() + + @property + def is_indicator(self): + return self.isIndicator() + + def fresh_copy(self, scope=None): + if scope is None: + return self.freshCopy() + else: + return self.freshCopy(scope) + @jpype.JImplementationFor("it.unibo.tuprolog.core.operators.Operator") class _KtOperator: @@ -47,10 +150,90 @@ def functor(self): def args(self): return self.getArgs() + @property + def argsSequence(self): + return self.getArgsSequence() + @property def arity(self): return self.getArity() + @property + def is_functor_well_formed(self): + return self.isFunctorWellFormed() + + @property + def indicator(self): + return self.getIndicator() + + def get_arg_at(self, index): + return self.getArgAt(index) + + def add_last(self, argument): + return self.addLast(argument) + + def add_first(self, argument): + return self.addFirst(argument) + + def insert_at(self, index, argument): + return self.addFirst(index, argument) + + def set_functor(self, functor): + return self.setFunctor(functor) + + def set_args(self, *args): + return iterable_or_varargs(args, lambda xs: self.setArgs(args)) + + +@jpype.JImplementationFor("it.unibo.tuprolog.core.Var") +class _KtConstant: + def __jclass_init__(self): + pass + + @property + def is_anonymous(self): + return self.isAnonymous() + + @property + def name(self): + return self.getName() + + @property + def id(self): + return self.getId() + + @property + def complete_name(self): + return self.getCompleteName() + + @property + def is_name_well_formed(self): + return self.isNameWellFormed() + + +@jpype.JImplementationFor("it.unibo.tuprolog.core.Constant") +class _KtConstant: + def __jclass_init__(self): + pass + + @property + def value(self): + return self.getValue() + + +@jpype.JImplementationFor("it.unibo.tuprolog.core.Numeric") +class _KtNumeric: + def __jclass_init__(self): + pass + + @property + def int_value(self): + return self.getIntValue() + + @property + def decimal_value(self): + return self.getDecimalValue() + @jpype.JImplementationFor("it.unibo.tuprolog.core.Clause") class _KtClause: From 7f4c58d1a422cd2684302f144897a2cdf52c03d3 Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Wed, 13 Oct 2021 08:52:14 +0200 Subject: [PATCH 002/154] [wip] harmonising types in tuprolog.core, ok up to Rules --- tuprolog/core/_ktadapt.py | 112 +++++++++++++++++++++++++++++++++++--- 1 file changed, 103 insertions(+), 9 deletions(-) diff --git a/tuprolog/core/_ktadapt.py b/tuprolog/core/_ktadapt.py index 09f4142..a59d4f4 100644 --- a/tuprolog/core/_ktadapt.py +++ b/tuprolog/core/_ktadapt.py @@ -2,12 +2,15 @@ import jpype +from typing import Sized + +from tuprolog.jvmutils import jiterable from tuprolog.pyutils import iterable_or_varargs @jpype.JImplementationFor("it.unibo.tuprolog.core.Term") class _KtTerm: - def __jclass_init__(self): + def __jclass_init__(cls): pass def __getitem__(self, item, *items): @@ -121,7 +124,7 @@ def fresh_copy(self, scope=None): @jpype.JImplementationFor("it.unibo.tuprolog.core.operators.Operator") class _KtOperator: - def __jclass_init__(self): + def __jclass_init__(cls): pass @property @@ -139,7 +142,7 @@ def priority(self): @jpype.JImplementationFor("it.unibo.tuprolog.core.Struct") class _KtStruct: - def __jclass_init__(self): + def __jclass_init__(cls): pass @property @@ -182,12 +185,12 @@ def set_functor(self, functor): return self.setFunctor(functor) def set_args(self, *args): - return iterable_or_varargs(args, lambda xs: self.setArgs(args)) + return iterable_or_varargs(args, lambda xs: self.setArgs(jiterable(args))) @jpype.JImplementationFor("it.unibo.tuprolog.core.Var") -class _KtConstant: - def __jclass_init__(self): +class _KtVar: + def __jclass_init__(cls): pass @property @@ -213,7 +216,7 @@ def is_name_well_formed(self): @jpype.JImplementationFor("it.unibo.tuprolog.core.Constant") class _KtConstant: - def __jclass_init__(self): + def __jclass_init__(cls): pass @property @@ -223,7 +226,7 @@ def value(self): @jpype.JImplementationFor("it.unibo.tuprolog.core.Numeric") class _KtNumeric: - def __jclass_init__(self): + def __jclass_init__(cls): pass @property @@ -235,9 +238,33 @@ def decimal_value(self): return self.getDecimalValue() +@jpype.JImplementationFor("it.unibo.tuprolog.core.Recursive") +class _KtRecursive: + def __jclass_init__(cls): + Sized.register(cls) + + @property + def lazily_unfolded(self): + return self.getUnfoldedSequence() + + @property + def unfolded(self): + return self.getUnfoldedList() + + @property + def __len__(self): + return self.getSize() + + def to_iterable(self): + return self.toSequence() + + def to_list(self): + return self.toList() + + @jpype.JImplementationFor("it.unibo.tuprolog.core.Clause") class _KtClause: - def __jclass_init__(self): + def __jclass_init__(cls): pass @property @@ -252,5 +279,72 @@ def body(self): def is_well_formed(self): return self.isWellFormed() + @property + def body_items(self): + return self.getBodyItems() + + @property + def body_size(self): + return self.getBodySize() + + def get_body_item(self, index): + return self.getBodyItem(index) + + def set_head(self, head): + return self.setHead(head) + + def set_body(self, term): + return self.setBody(term) + + def set_head_functor(self, functor): + return self.setHeadFunctor(functor) + + def set_head_args(self, *args): + return iterable_or_varargs(args, lambda xs: self.setHeadArgs(jiterable(args))) + + def insert_head_arg(self, index, argument): + return self.setHeadArg(index, argument) + + def add_first_head_arg(self, argument): + return self.addFirstHeadArg(argument) + + def add_last_head_arg(self, argument): + return self.addLastHeadArg(argument) + + def append_head_arg(self, argument): + return self.appendHeadArg(argument) + + def set_body_items(self, *args): + return iterable_or_varargs(args, lambda xs: self.setBodyItems(jiterable(args))) + + def insert_body_item(self, index, item): + return self.insertBodyItem(index, item) + + def add_first_body_item(self, item): + return self.addFirstBodyItem(item) + + def add_last_body_item(self, item): + return self.addLastBodyItem(item) + + def append_body_item(self, item): + return self.appendBodyItem(item) + + +@jpype.JImplementationFor("it.unibo.tuprolog.core.Rule") +class _KtRule: + def __jclass_init__(cls): + pass + + @property + def head_args(self): + return self.getHeadArgs() + + @property + def head_arity(self): + return self.getHeadArity() + + def get_head_arg(self, index): + return self.getHeadArg(index) + logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.core.*") From a3f74f8280c9cb7c0c95a575bd45fe8fb58a3ca8 Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Fri, 15 Oct 2021 17:13:37 +0200 Subject: [PATCH 003/154] harmonize types in tuprolog.core --- tuprolog/core/_ktadapt.py | 118 ++++++++++++++---- .../{operators.py => operators/__init__.py} | 4 +- tuprolog/core/operators/_ktadapt.py | 31 +++++ tuprolog/core/parsing.py | 1 - tuprolog/utils/__init__.py | 5 + tuprolog/utils/_ktadapt.py | 24 ++++ 6 files changed, 157 insertions(+), 26 deletions(-) rename tuprolog/core/{operators.py => operators/__init__.py} (93%) create mode 100644 tuprolog/core/operators/_ktadapt.py create mode 100644 tuprolog/utils/__init__.py create mode 100644 tuprolog/utils/_ktadapt.py diff --git a/tuprolog/core/_ktadapt.py b/tuprolog/core/_ktadapt.py index a59d4f4..61cb749 100644 --- a/tuprolog/core/_ktadapt.py +++ b/tuprolog/core/_ktadapt.py @@ -1,11 +1,10 @@ from tuprolog import logger - import jpype - -from typing import Sized - +from tuprolog.utils import * +from typing import Sized, Callable from tuprolog.jvmutils import jiterable from tuprolog.pyutils import iterable_or_varargs +from tuprolog.jvmutils import kfunction @jpype.JImplementationFor("it.unibo.tuprolog.core.Term") @@ -122,24 +121,6 @@ def fresh_copy(self, scope=None): return self.freshCopy(scope) -@jpype.JImplementationFor("it.unibo.tuprolog.core.operators.Operator") -class _KtOperator: - def __jclass_init__(cls): - pass - - @property - def functor(self): - return self.getFunctor() - - @property - def specifier(self): - return self.getSpecifier() - - @property - def priority(self): - return self.getPriority() - - @jpype.JImplementationFor("it.unibo.tuprolog.core.Struct") class _KtStruct: def __jclass_init__(cls): @@ -261,6 +242,54 @@ def to_iterable(self): def to_list(self): return self.toList() + def to_array(self): + return self.toArray() + + +@jpype.JImplementationFor("it.unibo.tuprolog.core.List") +class _KtList: + def __jclass_init__(cls): + pass + + @property + def is_well_formed(self): + return self.isWellFormed() + + @property + def last(self): + return self.getLast() + + def estimated_length(self): + return self.getEstimatedLength() + + +@jpype.JImplementationFor("it.unibo.tuprolog.core.Cons") +class _KtCons: + def __jclass_init__(cls): + pass + + @property + def head(self): + return self.getHead() + + @property + def tail(self): + return self.getTail() + + +@jpype.JImplementationFor("it.unibo.tuprolog.core.Tuple") +class _KtTuple: + def __jclass_init__(cls): + pass + + @property + def left(self): + return self.getLeft() + + @property + def right(self): + return self.getRight() + @jpype.JImplementationFor("it.unibo.tuprolog.core.Clause") class _KtClause: @@ -347,4 +376,49 @@ def get_head_arg(self, index): return self.getHeadArg(index) +@jpype.JImplementationFor("it.unibo.tuprolog.core.TermConvertible") +class _KtTermConvertible: + def __jclass_init__(cls): + pass + + def to_term(self): + return self.toTerm() + + +@jpype.JImplementationFor("it.unibo.tuprolog.core.Substitution") +class _KtSubstitution: + def __jclass_init__(cls): + pass + + @property + def is_success(self): + return self.isSuccess() + + @property + def is_failed(self): + return self.isFailed() + + def apply_to(self, term): + return self.applyTo(term) + + def get_original(self, variable): + return self.getOriginal(variable) + + def get_by_name(self, name): + return self.getByName(name) + + def __add__(self, other): + return self.plus(other) + + def __sub__(self, other): + return self.minus(other) + + @jpype.JOverride + def filter(self, filter): + if isinstance(filter, Callable): + return self.filter_(kfunction(1)(filter)) + else: + return self.filter_(filter) + + logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.core.*") diff --git a/tuprolog/core/operators.py b/tuprolog/core/operators/__init__.py similarity index 93% rename from tuprolog/core/operators.py rename to tuprolog/core/operators/__init__.py index 604b012..695db49 100644 --- a/tuprolog/core/operators.py +++ b/tuprolog/core/operators/__init__.py @@ -1,4 +1,5 @@ from tuprolog import logger +from ._ktadapt import * # noinspection PyUnresolvedReferences import jpype # noinspection PyUnresolvedReferences @@ -67,8 +68,5 @@ def _(term: Term) -> Specifier: YFX: Specifier = Specifier.YFX -OperatorSet.__add__ = lambda this, other: this.plus(other) -OperatorSet.__sub__ = lambda this, other: this.minus(other) - logger.debug("Loaded JVM classes from it.unibo.tuprolog.core.operators.*") diff --git a/tuprolog/core/operators/_ktadapt.py b/tuprolog/core/operators/_ktadapt.py new file mode 100644 index 0000000..9fdac4d --- /dev/null +++ b/tuprolog/core/operators/_ktadapt.py @@ -0,0 +1,31 @@ +import jpype + + +@jpype.JImplementationFor("it.unibo.tuprolog.core.operators.Operator") +class _KtOperator: + def __jclass_init__(cls): + pass + + @property + def functor(self): + return self.getFunctor() + + @property + def specifier(self): + return self.getSpecifier() + + @property + def priority(self): + return self.getPriority() + + +@jpype.JImplementationFor("it.unibo.tuprolog.core.operators.OperatorSet") +class _KtOperatorSet: + def __jclass_init__(cls): + pass + + def __add__(self, other): + return self.plus(other) + + def __sub__(self, other): + return self.minus(other) diff --git a/tuprolog/core/parsing.py b/tuprolog/core/parsing.py index 3ebf426..b19977a 100644 --- a/tuprolog/core/parsing.py +++ b/tuprolog/core/parsing.py @@ -14,7 +14,6 @@ InvalidTermTypeException = _parsing.InvalidTermTypeException -# noinspection PyUnresolvedReferences from tuprolog.core.operators import Operator, OperatorSet, DEFAULT_OPERATORS, EMPTY_OPERATORS from typing import Union, Iterable diff --git a/tuprolog/utils/__init__.py b/tuprolog/utils/__init__.py new file mode 100644 index 0000000..f7a7b53 --- /dev/null +++ b/tuprolog/utils/__init__.py @@ -0,0 +1,5 @@ +from tuprolog import logger +from ._ktadapt import * + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.utils.*") diff --git a/tuprolog/utils/_ktadapt.py b/tuprolog/utils/_ktadapt.py new file mode 100644 index 0000000..ecff775 --- /dev/null +++ b/tuprolog/utils/_ktadapt.py @@ -0,0 +1,24 @@ +from tuprolog import logger +import jpype + + +@jpype.JImplementationFor("it.unibo.tuprolog.utils.Taggable") +class _KtTaggable: + def __jclass_init__(cls): + pass + + @property + def tags(self): + return self.getTags() + + def get_tag(self, name): + return self.getTag(name) + + def replace_tags(self, tags): + return self.replaceTags(tags) + + def contains_tag(self, name): + return self.containsTag(name) + + +logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.utils.*") From 1d7a76e03b627ad34d661556d8c5a60dce17e578 Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Fri, 15 Oct 2021 18:32:44 +0200 Subject: [PATCH 004/154] wip improving ktmath --- tuprolog/core/__init__.py | 1 + tuprolog/core/_ktmath.py | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tuprolog/core/__init__.py b/tuprolog/core/__init__.py index e107356..6393a6e 100644 --- a/tuprolog/core/__init__.py +++ b/tuprolog/core/__init__.py @@ -9,6 +9,7 @@ from typing import Iterable, Union, Dict from ._ktmath import * + Atom = _core.Atom Block = _core.Block diff --git a/tuprolog/core/_ktmath.py b/tuprolog/core/_ktmath.py index 6482181..e45af66 100644 --- a/tuprolog/core/_ktmath.py +++ b/tuprolog/core/_ktmath.py @@ -1,4 +1,6 @@ # noinspection PyUnresolvedReferences +from typing import Union + import jpype.imports # noinspection PyUnresolvedReferences import org.gciatto.kt.math as _ktmath @@ -13,8 +15,13 @@ RoundingMode = _ktmath.RoundingMode -def big_integer(value) -> BigInteger: - return BigInteger.Companion.of(value) +def big_integer(value: Union[str, int], radix: int = None) -> BigInteger: + if radix is not None: + assert isinstance(value, str) + return BigInteger.Companion.of(value, radix) + if isinstance(value, str): + return BigInteger.Companion.of(jpype.JString@value) + return BigInteger.Companion.of(jpype.JLong@value) def big_decimal(value) -> BigDecimal: From 29c121279a0502a9fc325e3196b5d194934e8de5 Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Sun, 17 Oct 2021 19:19:49 +0200 Subject: [PATCH 005/154] [wip] harmonising types of kt-math --- tuprolog/core/_ktmath.py | 57 +++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/tuprolog/core/_ktmath.py b/tuprolog/core/_ktmath.py index e45af66..1628a89 100644 --- a/tuprolog/core/_ktmath.py +++ b/tuprolog/core/_ktmath.py @@ -1,10 +1,11 @@ # noinspection PyUnresolvedReferences from typing import Union - +import decimal import jpype.imports # noinspection PyUnresolvedReferences import org.gciatto.kt.math as _ktmath - +# noinspection PyUnresolvedReferences +import java.lang as _java_lang BigInteger = _ktmath.BigInteger @@ -14,15 +15,57 @@ RoundingMode = _ktmath.RoundingMode +_MAX_LONG = _java_lang.Long.MAX_VALUE + def big_integer(value: Union[str, int], radix: int = None) -> BigInteger: if radix is not None: assert isinstance(value, str) - return BigInteger.Companion.of(value, radix) + return BigInteger.of(value, radix) if isinstance(value, str): - return BigInteger.Companion.of(jpype.JString@value) - return BigInteger.Companion.of(jpype.JLong@value) + return BigInteger.of(jpype.JString @ value) + assert isinstance(value, int) + if value > _MAX_LONG: + return BigInteger.of(jpype.JString @ str(value)) + return BigInteger.of(jpype.JInt @ value) + + +def jvm_rounding_mode(mode): + if mode == decimal.ROUND_DOWN: + return RoundingMode.DOWN + elif mode == decimal.ROUND_UP: + return RoundingMode.UP + elif mode == decimal.ROUND_FLOOR: + return RoundingMode.FLOOR + elif mode == decimal.ROUND_CEILING: + return RoundingMode.CEILING + elif mode == decimal.ROUND_HALF_UP: + return RoundingMode.HALF_UP + elif mode == decimal.ROUND_HALF_EVEN: + return RoundingMode.HALF_EVEN + elif mode == decimal.ROUND_HALF_DOWN: + return RoundingMode.HALF_DOWN + elif mode == decimal.ROUND_05UP: + raise ValueError(f"Rounding mode {decimal.ROUND_05UP} has no Java correspondence") + else: + raise ValueError(f"Not a rounding mode {mode}") -def big_decimal(value) -> BigDecimal: - return BigDecimal.Companion.of(value) +def big_decimal(value: Union[str, int, float, decimal.Decimal], precision=None, rounding=None) -> BigDecimal: + if precision is None: + precision = decimal.getcontext().prec + assert isinstance(precision, int) + if rounding is None: + rounding = jvm_rounding_mode(decimal.getcontext().rounding) + elif rounding in decimal: + rounding = jvm_rounding_mode(rounding) + assert isinstance(rounding, RoundingMode) + context = MathContext(precision, rounding) + if isinstance(value, decimal.Decimal): + return BigDecimal.of(jpype.JString @ str(value), context) + if isinstance(value, BigInteger): + return BigDecimal.of(value, context) + if isinstance(value, int): + return BigDecimal.of(big_integer(value), context) + assert isinstance(value, float) + return BigDecimal.of(jpype.JDouble @ value, context) From a474b692bc82a03fc9d52492dace50d8428af39f Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Mon, 18 Oct 2021 19:12:36 +0200 Subject: [PATCH 006/154] efficient big integer conversion + test --- test/core/test_kt_math.py | 40 +++++++++++++++++++++++++++++++++++++++ tuprolog/core/_ktmath.py | 38 ++++++++++++++++++++++++++++++++++--- 2 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 test/core/test_kt_math.py diff --git a/test/core/test_kt_math.py b/test/core/test_kt_math.py new file mode 100644 index 0000000..71796bd --- /dev/null +++ b/test/core/test_kt_math.py @@ -0,0 +1,40 @@ +import unittest +from tuprolog import * +from tuprolog.core import * + + +class TestBigInteger(unittest.TestCase): + + def setUp(self): + self.large_int = 1 << 64 + + def assertSameStringRepresentation(self, expected, actual): + self.assertEqual(str(expected), str(actual)) + + def test_python_to_java(self): + self.assertSameStringRepresentation(0, big_integer("0")) + self.assertSameStringRepresentation(0, big_integer(0)) + self.assertSameStringRepresentation(1, big_integer("1")) + self.assertSameStringRepresentation(1, big_integer(1)) + self.assertSameStringRepresentation(self.large_int, big_integer(self.large_int)) + self.assertSameStringRepresentation(-1, big_integer("-1")) + self.assertSameStringRepresentation(-1, big_integer(-1)) + self.assertSameStringRepresentation(-self.large_int, big_integer(-self.large_int)) + self.assertSameStringRepresentation(0x16, big_integer("16", 16)) + self.assertSameStringRepresentation(-0x16, big_integer("-16", 16)) + + def test_java_to_python(self): + self.assertEquals(0, python_integer(big_integer("0"))) + self.assertEquals(0, python_integer(big_integer(0))) + self.assertEquals(1, python_integer(big_integer("1"))) + self.assertEquals(1, python_integer(big_integer(1))) + self.assertEquals(self.large_int, python_integer(big_integer(self.large_int))) + self.assertEquals(-1, python_integer(big_integer("-1"))) + self.assertEquals(-1, python_integer(big_integer(-1))) + self.assertEquals(-self.large_int, python_integer(big_integer(-self.large_int))) + self.assertEquals(0x16, python_integer(big_integer("16", 16))) + self.assertEquals(-0x16, python_integer(big_integer("-16", 16))) + + +if __name__ == '__main__': + unittest.main() diff --git a/tuprolog/core/_ktmath.py b/tuprolog/core/_ktmath.py index 1628a89..b8669dc 100644 --- a/tuprolog/core/_ktmath.py +++ b/tuprolog/core/_ktmath.py @@ -6,6 +6,7 @@ import org.gciatto.kt.math as _ktmath # noinspection PyUnresolvedReferences import java.lang as _java_lang +from math import ceil BigInteger = _ktmath.BigInteger @@ -17,6 +18,30 @@ _MAX_LONG = _java_lang.Long.MAX_VALUE +_MIN_LONG = _java_lang.Long.MIN_VALUE + +BIG_INTEGER_MAX_LONG = BigInteger.of(_MAX_LONG) + +BIG_INTEGER_MIN_LONG = BigInteger.of(_MIN_LONG) + +BIG_INTEGER_ZERO = BigInteger.ZERO + +BIG_INTEGER_TEN = BigInteger.TEN + +BIG_INTEGER_ONE = BigInteger.ONE + +BIG_INTEGER_NEGATIVE_ONE = BigInteger.NEGATIVE_ONE + +BIG_INTEGER_TWO = BigInteger.TWO + + +def _size_of(n: int) -> int: + return max(ceil(n.bit_length() / 8), 1) + + +def _int_to_bytes(n: int) -> bytes: + return n.to_bytes(_size_of(n), 'big', signed=True) + def big_integer(value: Union[str, int], radix: int = None) -> BigInteger: if radix is not None: @@ -25,9 +50,12 @@ def big_integer(value: Union[str, int], radix: int = None) -> BigInteger: if isinstance(value, str): return BigInteger.of(jpype.JString @ value) assert isinstance(value, int) - if value > _MAX_LONG: - return BigInteger.of(jpype.JString @ str(value)) - return BigInteger.of(jpype.JInt @ value) + bs = _int_to_bytes(value) + return BigInteger(jpype.JArray(jpype.JByte) @ bs, 0, len(bs)) + + +def python_integer(value: BigInteger) -> int: + return int.from_bytes(value.toByteArray(), byteorder='big', signed=True) def jvm_rounding_mode(mode): @@ -69,3 +97,7 @@ def big_decimal(value: Union[str, int, float, decimal.Decimal], precision=None, return BigDecimal.of(big_integer(value), context) assert isinstance(value, float) return BigDecimal.of(jpype.JDouble @ value, context) + + +def python_decimal(value: BigDecimal) -> decimal.Decimal: + return decimal.Decimal(str(value)) From bd769e48e8ce4fdec5ce4b405be1adb6132515a5 Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Thu, 28 Oct 2021 18:45:22 +0200 Subject: [PATCH 007/154] add tests for kt-math --- test/core/test_kt_math.py | 155 ++++++++++++++++++++++++++++++++++++-- tuprolog/core/_ktmath.py | 26 ++++++- tuprolog/pyutils.py | 19 +++++ 3 files changed, 193 insertions(+), 7 deletions(-) diff --git a/test/core/test_kt_math.py b/test/core/test_kt_math.py index 71796bd..7f6bf9e 100644 --- a/test/core/test_kt_math.py +++ b/test/core/test_kt_math.py @@ -1,16 +1,22 @@ +from decimal import Decimal import unittest -from tuprolog import * -from tuprolog.core import * +from tuprolog.core import big_integer, python_integer, big_decimal, python_decimal, BIG_INTEGER_ZERO, BIG_INTEGER_TEN, \ + BIG_INTEGER_ONE, BIG_INTEGER_NEGATIVE_ONE, BIG_INTEGER_TWO, BIG_DECIMAL_PI, BIG_DECIMAL_E, BIG_DECIMAL_ONE_TENTH, \ + BIG_DECIMAL_ONE_HALF, BIG_DECIMAL_ONE, BIG_DECIMAL_ZERO -class TestBigInteger(unittest.TestCase): - def setUp(self): - self.large_int = 1 << 64 +class TestKtMath(unittest.TestCase): def assertSameStringRepresentation(self, expected, actual): self.assertEqual(str(expected), str(actual)) + +class TestBigInteger(TestKtMath): + + def setUp(self): + self.large_int = 1 << 64 + def test_python_to_java(self): self.assertSameStringRepresentation(0, big_integer("0")) self.assertSameStringRepresentation(0, big_integer(0)) @@ -35,6 +41,145 @@ def test_java_to_python(self): self.assertEquals(0x16, python_integer(big_integer("16", 16))) self.assertEquals(-0x16, python_integer(big_integer("-16", 16))) + def test_constants(self): + self.assertEquals(big_integer(0), BIG_INTEGER_ZERO) + self.assertEquals(big_integer(10), BIG_INTEGER_TEN) + self.assertEquals(big_integer(1), BIG_INTEGER_ONE) + self.assertEquals(big_integer(-1), BIG_INTEGER_NEGATIVE_ONE) + self.assertEquals(big_integer(2), BIG_INTEGER_TWO) + + +class TestBigDecimal(TestKtMath): + + def setUp(self): + self.e = '2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852' + \ + '5166427427466391932003059921817413596629043572900334295260595630738132328627943490763233829880' + \ + '753195251019011573834187930702154089149934884167509244761460668082264' + + self.pi = '3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253' + \ + '421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446' + \ + '22948954930381964428810975665933446128475648233786783165271201909145648' + + self.one_tenth = "0.01000000000000000020816681711721685132943093776702880859375" + + def test_python_to_java_zero(self): + self.assertSameStringRepresentation(0, big_decimal("0")) + self.assertSameStringRepresentation(0, big_decimal("0.0")) + self.assertSameStringRepresentation(0, big_decimal("0.00")) + self.assertSameStringRepresentation(0, big_decimal(0)) + self.assertSameStringRepresentation(0, big_decimal(0.0)) + self.assertSameStringRepresentation(0, big_decimal(0.00)) + self.assertSameStringRepresentation(0, big_decimal(Decimal(0))) + self.assertSameStringRepresentation(0, big_decimal(Decimal(0.0))) + self.assertSameStringRepresentation(0, big_decimal(Decimal(0.00))) + + def test_python_to_java_one(self): + self.assertSameStringRepresentation(1, big_decimal("1")) + self.assertSameStringRepresentation(1, big_decimal("1.0")) + self.assertSameStringRepresentation(1, big_decimal("1.00")) + self.assertSameStringRepresentation(1, big_decimal(1)) + self.assertSameStringRepresentation(1, big_decimal(1.0)) + self.assertSameStringRepresentation(1, big_decimal(1.00)) + self.assertSameStringRepresentation(1, big_decimal(Decimal(1))) + self.assertSameStringRepresentation(1, big_decimal(Decimal(1.0))) + self.assertSameStringRepresentation(1, big_decimal(Decimal(1.00))) + + def test_python_to_java_minus_one(self): + self.assertSameStringRepresentation(-1, big_decimal("-1")) + self.assertSameStringRepresentation(-1, big_decimal("-1.0")) + self.assertSameStringRepresentation(-1, big_decimal("-1.00")) + self.assertSameStringRepresentation(-1, big_decimal(-1)) + self.assertSameStringRepresentation(-1, big_decimal(-1.0)) + self.assertSameStringRepresentation(-1, big_decimal(-1.00)) + self.assertSameStringRepresentation(-1, big_decimal(Decimal(-1))) + self.assertSameStringRepresentation(-1, big_decimal(Decimal(-1.0))) + self.assertSameStringRepresentation(-1, big_decimal(Decimal(-1.00))) + + def test_python_to_java_one_half(self): + self.assertSameStringRepresentation(0.5, big_decimal("0.5")) + self.assertSameStringRepresentation(0.5, big_decimal("0.50")) + self.assertSameStringRepresentation(0.5, big_decimal("0.500")) + self.assertSameStringRepresentation(0.5, big_decimal(0.5)) + self.assertSameStringRepresentation(0.5, big_decimal(0.50)) + self.assertSameStringRepresentation(0.5, big_decimal(0.500)) + self.assertSameStringRepresentation(0.5, big_decimal(Decimal(0.5))) + self.assertSameStringRepresentation(0.5, big_decimal(Decimal(0.50))) + self.assertSameStringRepresentation(0.5, big_decimal(Decimal(0.500))) + + def test_python_to_java_one_cent(self): + self.assertSameStringRepresentation(0.01, big_decimal("0.01")) + self.assertSameStringRepresentation(0.01, big_decimal("0.010")) + self.assertSameStringRepresentation(0.01, big_decimal("0.0100")) + self.assertSameStringRepresentation(0.01, big_decimal(0.01)) + self.assertSameStringRepresentation(0.01, big_decimal(0.010)) + self.assertSameStringRepresentation(0.01, big_decimal(0.0100)) + self.assertSameStringRepresentation(self.one_tenth, big_decimal(Decimal(0.01))) + self.assertSameStringRepresentation(self.one_tenth, big_decimal(Decimal(0.010))) + self.assertSameStringRepresentation(self.one_tenth, big_decimal(Decimal(0.0100))) + + def test_java_to_python_zero(self): + self.assertSameStringRepresentation(Decimal(0), python_decimal(big_decimal("0"))) + self.assertSameStringRepresentation(Decimal(0), python_decimal(big_decimal("0.0"))) + self.assertSameStringRepresentation(Decimal(0), python_decimal(big_decimal("0.00"))) + self.assertSameStringRepresentation(Decimal(0), python_decimal(big_decimal(0))) + self.assertSameStringRepresentation(Decimal(0), python_decimal(big_decimal(0.0))) + self.assertSameStringRepresentation(Decimal(0), python_decimal(big_decimal(0.00))) + self.assertSameStringRepresentation(Decimal(0), python_decimal(big_decimal(Decimal(0)))) + self.assertSameStringRepresentation(Decimal(0), python_decimal(big_decimal(Decimal(0.0)))) + self.assertSameStringRepresentation(Decimal(0), python_decimal(big_decimal(Decimal(0.00)))) + + def test_java_to_python_one(self): + self.assertSameStringRepresentation(Decimal(1), python_decimal(big_decimal("1"))) + self.assertSameStringRepresentation(Decimal(1), python_decimal(big_decimal("1.0"))) + self.assertSameStringRepresentation(Decimal(1), python_decimal(big_decimal("1.00"))) + self.assertSameStringRepresentation(Decimal(1), python_decimal(big_decimal(1))) + self.assertSameStringRepresentation(Decimal(1), python_decimal(big_decimal(1.0))) + self.assertSameStringRepresentation(Decimal(1), python_decimal(big_decimal(1.00))) + self.assertSameStringRepresentation(Decimal(1), python_decimal(big_decimal(Decimal(1)))) + self.assertSameStringRepresentation(Decimal(1), python_decimal(big_decimal(Decimal(1.0)))) + self.assertSameStringRepresentation(Decimal(1), python_decimal(big_decimal(Decimal(1.00)))) + + def test_java_to_python_minus_one(self): + self.assertSameStringRepresentation(Decimal(-1), python_decimal(big_decimal("-1"))) + self.assertSameStringRepresentation(Decimal(-1), python_decimal(big_decimal("-1.0"))) + self.assertSameStringRepresentation(Decimal(-1), python_decimal(big_decimal("-1.00"))) + self.assertSameStringRepresentation(Decimal(-1), python_decimal(big_decimal(-1))) + self.assertSameStringRepresentation(Decimal(-1), python_decimal(big_decimal(-1.0))) + self.assertSameStringRepresentation(Decimal(-1), python_decimal(big_decimal(-1.00))) + self.assertSameStringRepresentation(Decimal(-1), python_decimal(big_decimal(Decimal(-1)))) + self.assertSameStringRepresentation(Decimal(-1), python_decimal(big_decimal(Decimal(-1.0)))) + self.assertSameStringRepresentation(Decimal(-1), python_decimal(big_decimal(Decimal(-1.00)))) + + def test_java_to_python_one_half(self): + self.assertSameStringRepresentation(Decimal(0.5), python_decimal(big_decimal("0.5"))) + self.assertSameStringRepresentation(Decimal(0.5), python_decimal(big_decimal("0.50"))) + self.assertSameStringRepresentation(Decimal(0.5), python_decimal(big_decimal("0.500"))) + self.assertSameStringRepresentation(Decimal(0.5), python_decimal(big_decimal(0.5))) + self.assertSameStringRepresentation(Decimal(0.5), python_decimal(big_decimal(0.50))) + self.assertSameStringRepresentation(Decimal(0.5), python_decimal(big_decimal(0.500))) + self.assertSameStringRepresentation(Decimal(0.5), python_decimal(big_decimal(Decimal(0.5)))) + self.assertSameStringRepresentation(Decimal(0.5), python_decimal(big_decimal(Decimal(0.50)))) + self.assertSameStringRepresentation(Decimal(0.5), python_decimal(big_decimal(Decimal(0.500)))) + + def test_java_to_python_one_cent(self): + self.assertSameStringRepresentation(Decimal("0.01"), python_decimal(big_decimal("0.01"))) + self.assertSameStringRepresentation(Decimal("0.01"), python_decimal(big_decimal("0.010"))) + self.assertSameStringRepresentation(Decimal("0.01"), python_decimal(big_decimal("0.0100"))) + self.assertSameStringRepresentation(Decimal("0.01"), python_decimal(big_decimal(0.01))) + self.assertSameStringRepresentation(Decimal("0.01"), python_decimal(big_decimal(0.010))) + self.assertSameStringRepresentation(Decimal("0.01"), python_decimal(big_decimal(0.0100))) + self.assertSameStringRepresentation(Decimal(self.one_tenth), python_decimal(big_decimal(Decimal(0.01)))) + self.assertSameStringRepresentation(Decimal(self.one_tenth), python_decimal(big_decimal(Decimal(0.010)))) + self.assertSameStringRepresentation(Decimal(self.one_tenth), python_decimal(big_decimal(Decimal(0.0100)))) + + def test_constants(self): + self.assertEqual(big_decimal(0), BIG_DECIMAL_ZERO) + self.assertEqual(big_decimal(1), BIG_DECIMAL_ONE) + self.assertEqual(big_decimal(0.5), BIG_DECIMAL_ONE_HALF) + self.assertEqual(big_decimal("0.1"), BIG_DECIMAL_ONE_TENTH) + self.assertEqual(big_decimal(self.e), BIG_DECIMAL_E) + self.assertEqual(big_decimal(self.pi), BIG_DECIMAL_PI) + if __name__ == '__main__': unittest.main() diff --git a/tuprolog/core/_ktmath.py b/tuprolog/core/_ktmath.py index b8669dc..53bb8f6 100644 --- a/tuprolog/core/_ktmath.py +++ b/tuprolog/core/_ktmath.py @@ -8,6 +8,8 @@ import java.lang as _java_lang from math import ceil +from tuprolog.pyutils import and_then + BigInteger = _ktmath.BigInteger BigDecimal = _ktmath.BigDecimal @@ -34,6 +36,18 @@ BIG_INTEGER_TWO = BigInteger.TWO +BIG_DECIMAL_ZERO = BigDecimal.ZERO + +BIG_DECIMAL_ONE = BigDecimal.ONE + +BIG_DECIMAL_ONE_HALF = BigDecimal.ONE_HALF + +BIG_DECIMAL_ONE_TENTH = BigDecimal.ONE_TENTH + +BIG_DECIMAL_E = BigDecimal.E + +BIG_DECIMAL_PI = BigDecimal.PI + def _size_of(n: int) -> int: return max(ceil(n.bit_length() / 8), 1) @@ -58,6 +72,10 @@ def python_integer(value: BigInteger) -> int: return int.from_bytes(value.toByteArray(), byteorder='big', signed=True) +_python_rounding_modes = {decimal.ROUND_DOWN, decimal.ROUND_HALF_UP, decimal.ROUND_HALF_EVEN, decimal.ROUND_CEILING, + decimal.ROUND_FLOOR, decimal.ROUND_UP, decimal.ROUND_HALF_DOWN, decimal.ROUND_05UP} + + def jvm_rounding_mode(mode): if mode == decimal.ROUND_DOWN: return RoundingMode.DOWN @@ -79,16 +97,20 @@ def jvm_rounding_mode(mode): raise ValueError(f"Not a rounding mode {mode}") -def big_decimal(value: Union[str, int, float, decimal.Decimal], precision=None, rounding=None) -> BigDecimal: +@and_then(lambda bd: bd.stripTrailingZeros()) +def big_decimal(value: Union[str, int, float, decimal.Decimal], precision=0, + rounding=RoundingMode.HALF_UP) -> BigDecimal: if precision is None: precision = decimal.getcontext().prec assert isinstance(precision, int) if rounding is None: rounding = jvm_rounding_mode(decimal.getcontext().rounding) - elif rounding in decimal: + elif rounding in _python_rounding_modes: rounding = jvm_rounding_mode(rounding) assert isinstance(rounding, RoundingMode) context = MathContext(precision, rounding) + if isinstance(value, str): + return BigDecimal.of(value, context) if isinstance(value, decimal.Decimal): return BigDecimal.of(jpype.JString @ str(value), context) if isinstance(value, BigInteger): diff --git a/tuprolog/pyutils.py b/tuprolog/pyutils.py index 4640456..034c1a2 100644 --- a/tuprolog/pyutils.py +++ b/tuprolog/pyutils.py @@ -30,3 +30,22 @@ def dict_or_keyword_args( for k in kwargs: all_data[k] = kwargs[k] return dispatch(all_data) + + +def and_then(continuation): + def call_and_then_continue(function): + def wrapper(*args, **kwargs): + result = function(*args, **kwargs) + return continuation(result) + return wrapper + return call_and_then_continue + + +def apply_to_result(consumer): + def call_and_then_apply(function): + def wrapper(*args, **kwargs): + result = function(*args, **kwargs) + consumer(result) + return result + return wrapper + return call_and_then_apply From c2a3caf70a769bb4a69e07315b7a3d7e2a1de51d Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Fri, 5 Nov 2021 16:18:40 +0100 Subject: [PATCH 008/154] + problog support --- download-jars.sh | 2 +- tuprolog/__main__.py | 3 +++ tuprolog/solve/classic/__init__.py | 3 +++ tuprolog/solve/plp/__init__.py | 37 ++++++++++++++++++++++++++++ tuprolog/solve/problog/__init__.py | 37 ++++++++++++++++++++++++++++ tuprolog/solve/problog/operators.py | 15 ++++++++++++ tuprolog/solve/prolog/__init__.py | 38 ++++++++++++++++++++++++++--- tuprolog/utils/__init__.py | 5 ++++ 8 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 tuprolog/solve/plp/__init__.py create mode 100644 tuprolog/solve/problog/__init__.py create mode 100644 tuprolog/solve/problog/operators.py diff --git a/download-jars.sh b/download-jars.sh index 93da6b7..e4fcadc 100755 --- a/download-jars.sh +++ b/download-jars.sh @@ -4,7 +4,7 @@ get_latest_release() { TUPROLOG_GITHUB='tuProlog/2p-kt' TUPROLOG_VERSION=`get_latest_release $TUPROLOG_GITHUB` -TUPROLOG_JAR_URL="https://github.com/$TUPROLOG_GITHUB/releases/download/$TUPROLOG_VERSION/2p-repl-$TUPROLOG_VERSION-redist.jar" +TUPROLOG_JAR_URL="https://github.com/$TUPROLOG_GITHUB/releases/download/$TUPROLOG_VERSION/2p-$TUPROLOG_VERSION-full.jar" rm -rf tuprolog/libs/*.jar diff --git a/tuprolog/__main__.py b/tuprolog/__main__.py index 263451a..b6f61fc 100644 --- a/tuprolog/__main__.py +++ b/tuprolog/__main__.py @@ -27,6 +27,9 @@ from tuprolog.solve.stdlib.function import * from tuprolog.solve.classic import * from tuprolog.solve.prolog import * +from tuprolog.solve.plp import * +from tuprolog.solve.problog import * +from tuprolog.solve.problog.operators import * import code diff --git a/tuprolog/solve/classic/__init__.py b/tuprolog/solve/classic/__init__.py index c2de785..6dd76c4 100644 --- a/tuprolog/solve/classic/__init__.py +++ b/tuprolog/solve/classic/__init__.py @@ -1,3 +1,4 @@ +from tuprolog import logger from tuprolog.solve.flags import DEFAULT_FLAG_STORE, FlagStore from tuprolog.solve.library import libraries, Libraries from tuprolog.solve.channel import InputChannel, OutputChannel, std_out, std_in, std_err, warn @@ -31,3 +32,5 @@ def classic_solver( def classic_solver_factory() -> SolverFactory: return _CLASSIC_SOLVER_FACTORY + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.classic.*") \ No newline at end of file diff --git a/tuprolog/solve/plp/__init__.py b/tuprolog/solve/plp/__init__.py new file mode 100644 index 0000000..f06ef65 --- /dev/null +++ b/tuprolog/solve/plp/__init__.py @@ -0,0 +1,37 @@ +from tuprolog import logger +# noinspection PyUnresolvedReferences +import jpype.imports +# noinspection PyUnresolvedReferences +import it.unibo.tuprolog.solve as _solve +from tuprolog.utils import Taggable +from tuprolog.solve import SolveOptions +from typing import TypeVar + + +ProbExtensions = _solve.ProbExtensions + + +def probability(taggable: Taggable) -> float: + return ProbExtensions.getProbability(taggable) + + +T = TypeVar("T", bound=Taggable, covariant=True) + + +def set_probability(taggable: T) -> T: + return ProbExtensions.setProbability(taggable) + + +def is_probabilistic(solve_opts: SolveOptions) -> bool: + return ProbExtensions.isProbabilistic(solve_opts) + + +def set_probabilistic(solve_opts: SolveOptions, value: bool) -> SolveOptions: + return ProbExtensions.setProbabilistic(solve_opts, value) + + +def probabilistic(solve_opts: SolveOptions) -> SolveOptions: + return ProbExtensions.probabilistic(solve_opts) + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.plp.*") diff --git a/tuprolog/solve/problog/__init__.py b/tuprolog/solve/problog/__init__.py new file mode 100644 index 0000000..5ad628a --- /dev/null +++ b/tuprolog/solve/problog/__init__.py @@ -0,0 +1,37 @@ +from tuprolog import logger +from tuprolog.solve.flags import DEFAULT_FLAG_STORE, FlagStore +from tuprolog.solve.library import libraries, Libraries +from tuprolog.solve.channel import InputChannel, OutputChannel, std_out, std_in, std_err, warn +from tuprolog.theory import theory, mutable_theory, Theory +from tuprolog.solve import Solver, SolverFactory + + +_PROBLOG_SOLVER_FACTORY = Solver.getProblog() + + +def problog_solver( + libraries: Libraries = libraries(), + flags: FlagStore = DEFAULT_FLAG_STORE, + static_kb: Theory = theory(), + dynamic_kb: Theory = mutable_theory(), + std_in: InputChannel = std_in(), + std_out: OutputChannel = std_out(), + std_err: OutputChannel = std_err(), + warning: OutputChannel = warn(), + mutable: bool = True +) -> Solver: + if mutable: + return _PROBLOG_SOLVER_FACTORY.mutableSolverWithDefaultBuiltins( + libraries, flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning + ) + else: + return _PROBLOG_SOLVER_FACTORY.solverWithDefaultBuiltins( + libraries, flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning + ) + + +def problog_solver_factory() -> SolverFactory: + return _PROBLOG_SOLVER_FACTORY + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.problog.*") diff --git a/tuprolog/solve/problog/operators.py b/tuprolog/solve/problog/operators.py new file mode 100644 index 0000000..eb322cc --- /dev/null +++ b/tuprolog/solve/problog/operators.py @@ -0,0 +1,15 @@ +from tuprolog import logger +# noinspection PyUnresolvedReferences +import jpype.imports +# noinspection PyUnresolvedReferences +import it.unibo.tuprolog.solve.problog as _problog + +Operators = _problog.Operators + +ANNOTATION_OPERATOR = Operators.ANNOTATION_OPERATOR + +PROBLOG_SPECIFIC_OPERATORS = Operators.PROBLOG_SPECIFIC_OPERATORS + +PROBLOG_OPERATORS = Operators.PROBLOG_OPERATORS + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.problog.operators") diff --git a/tuprolog/solve/prolog/__init__.py b/tuprolog/solve/prolog/__init__.py index 7e47822..f7633e1 100644 --- a/tuprolog/solve/prolog/__init__.py +++ b/tuprolog/solve/prolog/__init__.py @@ -1,5 +1,37 @@ -from tuprolog.solve.classic import classic_solver, classic_solver_factory +from tuprolog import logger +from tuprolog.solve.flags import DEFAULT_FLAG_STORE, FlagStore +from tuprolog.solve.library import libraries, Libraries +from tuprolog.solve.channel import InputChannel, OutputChannel, std_out, std_in, std_err, warn +from tuprolog.theory import theory, mutable_theory, Theory +from tuprolog.solve import Solver, SolverFactory -prolog_solver = classic_solver -prolog_solver_factory = classic_solver_factory +_PROLOG_SOLVER_FACTORY = Solver.getProlog() + + +def prolog_solver( + libraries: Libraries = libraries(), + flags: FlagStore = DEFAULT_FLAG_STORE, + static_kb: Theory = theory(), + dynamic_kb: Theory = mutable_theory(), + std_in: InputChannel = std_in(), + std_out: OutputChannel = std_out(), + std_err: OutputChannel = std_err(), + warning: OutputChannel = warn(), + mutable: bool = True +) -> Solver: + if mutable: + return _PROLOG_SOLVER_FACTORY.mutableSolverWithDefaultBuiltins( + libraries, flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning + ) + else: + return _PROLOG_SOLVER_FACTORY.solverWithDefaultBuiltins( + libraries, flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning + ) + + +def prolog_solver_factory() -> SolverFactory: + return _PROLOG_SOLVER_FACTORY + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.prolog.*") diff --git a/tuprolog/utils/__init__.py b/tuprolog/utils/__init__.py index f7a7b53..cbbd797 100644 --- a/tuprolog/utils/__init__.py +++ b/tuprolog/utils/__init__.py @@ -1,5 +1,10 @@ from tuprolog import logger from ._ktadapt import * +# noinspection PyUnresolvedReferences +import jpype.imports +# noinspection PyUnresolvedReferences +import it.unibo.tuprolog.utils as _utils +Taggable = _utils.Taggable logger.debug("Loaded JVM classes from it.unibo.tuprolog.utils.*") From 67a9bd7f20bbb79ac40c8b260fc55e46ec53c488 Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Fri, 5 Nov 2021 16:54:52 +0100 Subject: [PATCH 009/154] + problog test & example --- test/core/test_kt_math.py | 30 +++++++------- test/solve/__init__.py | 0 test/solve/problog/__init__.py | 0 test/solve/problog/problog_example.py | 58 +++++++++++++++++++++++++++ tuprolog/solve/__init__.py | 4 +- tuprolog/solve/_ktadapt.py | 36 +++++++++++++++++ tuprolog/solve/plp/__init__.py | 18 ++++++++- 7 files changed, 126 insertions(+), 20 deletions(-) create mode 100644 test/solve/__init__.py create mode 100644 test/solve/problog/__init__.py create mode 100644 test/solve/problog/problog_example.py diff --git a/test/core/test_kt_math.py b/test/core/test_kt_math.py index 7f6bf9e..6cdea22 100644 --- a/test/core/test_kt_math.py +++ b/test/core/test_kt_math.py @@ -30,23 +30,23 @@ def test_python_to_java(self): self.assertSameStringRepresentation(-0x16, big_integer("-16", 16)) def test_java_to_python(self): - self.assertEquals(0, python_integer(big_integer("0"))) - self.assertEquals(0, python_integer(big_integer(0))) - self.assertEquals(1, python_integer(big_integer("1"))) - self.assertEquals(1, python_integer(big_integer(1))) - self.assertEquals(self.large_int, python_integer(big_integer(self.large_int))) - self.assertEquals(-1, python_integer(big_integer("-1"))) - self.assertEquals(-1, python_integer(big_integer(-1))) - self.assertEquals(-self.large_int, python_integer(big_integer(-self.large_int))) - self.assertEquals(0x16, python_integer(big_integer("16", 16))) - self.assertEquals(-0x16, python_integer(big_integer("-16", 16))) + self.assertEqual(0, python_integer(big_integer("0"))) + self.assertEqual(0, python_integer(big_integer(0))) + self.assertEqual(1, python_integer(big_integer("1"))) + self.assertEqual(1, python_integer(big_integer(1))) + self.assertEqual(self.large_int, python_integer(big_integer(self.large_int))) + self.assertEqual(-1, python_integer(big_integer("-1"))) + self.assertEqual(-1, python_integer(big_integer(-1))) + self.assertEqual(-self.large_int, python_integer(big_integer(-self.large_int))) + self.assertEqual(0x16, python_integer(big_integer("16", 16))) + self.assertEqual(-0x16, python_integer(big_integer("-16", 16))) def test_constants(self): - self.assertEquals(big_integer(0), BIG_INTEGER_ZERO) - self.assertEquals(big_integer(10), BIG_INTEGER_TEN) - self.assertEquals(big_integer(1), BIG_INTEGER_ONE) - self.assertEquals(big_integer(-1), BIG_INTEGER_NEGATIVE_ONE) - self.assertEquals(big_integer(2), BIG_INTEGER_TWO) + self.assertEqual(big_integer(0), BIG_INTEGER_ZERO) + self.assertEqual(big_integer(10), BIG_INTEGER_TEN) + self.assertEqual(big_integer(1), BIG_INTEGER_ONE) + self.assertEqual(big_integer(-1), BIG_INTEGER_NEGATIVE_ONE) + self.assertEqual(big_integer(2), BIG_INTEGER_TWO) class TestBigDecimal(TestKtMath): diff --git a/test/solve/__init__.py b/test/solve/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/solve/problog/__init__.py b/test/solve/problog/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/solve/problog/problog_example.py b/test/solve/problog/problog_example.py new file mode 100644 index 0000000..60e8c4b --- /dev/null +++ b/test/solve/problog/problog_example.py @@ -0,0 +1,58 @@ +import unittest +from tuprolog.core import struct, var +from tuprolog.theory.parsing import parse_theory +from tuprolog.solve.plp import solve_options, probability +from tuprolog.solve.problog import problog_solver +from tuprolog.solve.problog.operators import PROBLOG_OPERATORS + + +class ExemplifyProblog(unittest.TestCase): + + def setUp(self) -> None: + self.probabilisticTheoryText = """ + 0.6::edge(1,2). + 0.1::edge(1,3). + 0.4::edge(2,5). + 0.3::edge(2,6). + 0.3::edge(3,4). + 0.8::edge(4,5). + 0.2::edge(5,6). + + path(X,Y) :- edge(X,Y). + path(X,Y) :- edge(X,Z),Y \\== Z,path(Z,Y). + """ + self.prints = [] + + def print(self, message): + self.prints.append(message) + + def test_problog(self): + probabilisticTheory = parse_theory(self.probabilisticTheoryText, PROBLOG_OPERATORS) + probabilisticSolver = problog_solver(static_kb=probabilisticTheory) + query = struct('path', var('From'), var('To')) + for solution in probabilisticSolver.solve(query, solve_options(lazy=True, probabilistic=True)): + if solution.is_yes: + self.print(f"yes: {solution.solved_query} with probability {probability(solution)}") + + self.assertEquals( + self.prints, + [ + 'yes: path(1, 2) with probability 0.6', + 'yes: path(1, 3) with probability 0.1', + 'yes: path(2, 5) with probability 0.4', + 'yes: path(2, 6) with probability 0.356', + 'yes: path(3, 4) with probability 0.3', + 'yes: path(4, 5) with probability 0.8', + 'yes: path(5, 6) with probability 0.2', + 'yes: path(1, 5) with probability 0.25824', + 'yes: path(1, 6) with probability 0.2167296', + 'yes: path(1, 4) with probability 0.03', + 'yes: path(3, 5) with probability 0.24', + 'yes: path(3, 6) with probability 0.04800000000000001', + 'yes: path(4, 6) with probability 0.16000000000000003' + ] + ) + + +if __name__ == '__main__': + unittest.main() diff --git a/tuprolog/solve/__init__.py b/tuprolog/solve/__init__.py index c915e33..330789b 100644 --- a/tuprolog/solve/__init__.py +++ b/tuprolog/solve/__init__.py @@ -1,15 +1,13 @@ from tuprolog import logger # noinspection PyUnresolvedReferences import jpype.imports - +from ._ktadapt import * # noinspection PyUnresolvedReferences import it.unibo.tuprolog.solve as _solve from tuprolog.core import Indicator, Struct, Term, Substitution, EMPTY_UNIFIER, TermFormatter from tuprolog.solve.exception import ResolutionException from tuprolog.jvmutils import jlist, jmap, JavaSystem - from functools import singledispatch - from typing import Iterable, Mapping, Any diff --git a/tuprolog/solve/_ktadapt.py b/tuprolog/solve/_ktadapt.py index b123ce1..8a21f73 100644 --- a/tuprolog/solve/_ktadapt.py +++ b/tuprolog/solve/_ktadapt.py @@ -10,4 +10,40 @@ def __jclass_init__(self): pass +@jpype.JImplementationFor("it.unibo.tuprolog.solve.Solution") +class _KtSolution: + def __jclass_init__(self): + pass + + @property + def is_yes(self): + return self.isYes() + + @property + def is_no(self): + return self.isNo() + + @property + def is_halt(self): + return self.isHalt() + + @property + def substitution(self): + return self.getSubstitution() + + @property + def exception(self): + return self.getExecption() + + @property + def solved_query(self): + return self.getSolvedQuery() + + def clean_up(self): + return self.cleanUp() + + def value_of(self, variable): + return self.valueOf(variable) + + logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.solve.*") diff --git a/tuprolog/solve/plp/__init__.py b/tuprolog/solve/plp/__init__.py index f06ef65..61a0679 100644 --- a/tuprolog/solve/plp/__init__.py +++ b/tuprolog/solve/plp/__init__.py @@ -4,8 +4,8 @@ # noinspection PyUnresolvedReferences import it.unibo.tuprolog.solve as _solve from tuprolog.utils import Taggable -from tuprolog.solve import SolveOptions -from typing import TypeVar +from tuprolog.solve import SolveOptions, solve_options as _solve_options, MAX_TIMEOUT, ALL_SOLUTIONS +from typing import TypeVar, Mapping, Any ProbExtensions = _solve.ProbExtensions @@ -34,4 +34,18 @@ def probabilistic(solve_opts: SolveOptions) -> SolveOptions: return ProbExtensions.probabilistic(solve_opts) +def solve_options( + lazy: bool = True, + timeout: int = MAX_TIMEOUT, + limit: int = ALL_SOLUTIONS, + probabilistic: bool = False, + custom: Mapping[str, Any] = dict(), + **kwargs: Any +) -> SolveOptions: + non_probabilistic = _solve_options(lazy, timeout, limit, custom, **kwargs) + if probabilistic: + return set_probabilistic(non_probabilistic, True) + return non_probabilistic + + logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.plp.*") From b50f6257aa65fbc754d00e07436deade507406a0 Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Sat, 6 Nov 2021 10:42:33 +0100 Subject: [PATCH 010/154] improve publication process --- .github/workflows/deploy.yml | 20 ++++++++++++++++++-- .github/workflows/quick-check.yml | 5 ----- setup.py | 22 ++++++++++++++++++---- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ad7c410..a425edd 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,8 +1,6 @@ name: deploy on: push: -# tags: -# - '[0-9]+.[0-9]+.[0-9]+' branches: - develop - master @@ -55,3 +53,21 @@ jobs: env: TWINE_USERNAME: ${{ secrets.PYPI_USERANAME }} TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + + - name: Get Version + id: get-version + run: echo ::set-output name=version::$(python setup.py get_project_version | tail -n 1) + + - name: Release Assets + id: upload-release-assets + run: | + set -x + ASSETS=() + for A in dist/*; do + ASSETS+=("-a" "$A") + echo "Releasing $A" + done + RELEASE_TAG='${{ steps.get-version.outputs.version }}' + hub release create "${ASSETS[@]}" -m "$RELEASE_TAG" "$RELEASE_TAG" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/quick-check.yml b/.github/workflows/quick-check.yml index b538daf..9ba0f22 100644 --- a/.github/workflows/quick-check.yml +++ b/.github/workflows/quick-check.yml @@ -6,10 +6,8 @@ on: - develop - 'feature/**' env: - # jdk-version: openjdk@~1.15.0 project-name: 2PPy workflow: quick-check - # gradle-options: "--no-daemon --console=plain --stacktrace" jobs: run-unit-tests: runs-on: ubuntu-latest @@ -26,9 +24,6 @@ jobs: with: fetch-depth: 0 # all history - # - name: Get All Tags - # run: git fetch --tags -f - - name: Restore Python dependencies run: pip install -r requirements.txt diff --git a/setup.py b/setup.py index e34e8d3..c55ebef 100644 --- a/setup.py +++ b/setup.py @@ -2,14 +2,13 @@ from setuptools import setup, find_packages import pathlib import subprocess +import distutils.cmd # current directory here = pathlib.Path(__file__).parent.resolve() version_file = here / 'VERSION' -print(f"Executing setup.py from {here}") - # Get the long description from the README file long_description = (here / 'README.md').read_text(encoding='utf-8') @@ -41,8 +40,20 @@ def get_version_from_git(): print(f"Detected version {version} from git describe") -# Arguments marked as "Required" below must be included for upload to PyPI. -# Fields marked as "Optional" may be commented out. +class GetVersionCommand(distutils.cmd.Command): + """A custom command to get the current project version inferred from git describe.""" + + description = 'gets the project version from git describe' + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + print(version) setup( name='2ppy', # Required @@ -83,4 +94,7 @@ def get_version_from_git(): # 'Say Thanks!': 'http://saythanks.io/to/example', 'Source': 'https://github.com/tuProlog/2ppy', }, + cmdclass={ + 'get_project_version': GetVersionCommand, + }, ) From a61c826bec1e84739316b4a4f5ba3dcbd408d16f Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Tue, 9 Nov 2021 17:09:28 +0100 Subject: [PATCH 011/154] port Scope --- test/core/test_scope.py | 23 +++++++++ test/core/test_visitors.py | 2 +- tuprolog/core/__init__.py | 64 +++++++++++-------------- tuprolog/core/_ktadapt.py | 98 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 150 insertions(+), 37 deletions(-) create mode 100644 test/core/test_scope.py diff --git a/test/core/test_scope.py b/test/core/test_scope.py new file mode 100644 index 0000000..d81d369 --- /dev/null +++ b/test/core/test_scope.py @@ -0,0 +1,23 @@ +import unittest +from tuprolog.core import scope, var, Scope + + +class TestScope(unittest.TestCase): + + def test_empty_scope_creation(self): + empty_scope = scope() + self.assertIsNotNone(empty_scope) + self.assertIsInstance(empty_scope, Scope) + self.assertEqual(0, len(empty_scope.variables)) + + def test_scope_creation(self): + full_scope = scope('A', var('B')) + self.assertIsNotNone(full_scope) + self.assertIsInstance(full_scope, Scope) + self.assertEqual(2, len(full_scope.variables)) + for v in full_scope.variables: + self.assertIn(v, {'A', 'B'}) + + +if __name__ == '__main__': + unittest.main() diff --git a/test/core/test_visitors.py b/test/core/test_visitors.py index 4fad903..d12cc43 100644 --- a/test/core/test_visitors.py +++ b/test/core/test_visitors.py @@ -16,4 +16,4 @@ def defaultValue(self, term): if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() diff --git a/tuprolog/core/__init__.py b/tuprolog/core/__init__.py index 6393a6e..1b2c56c 100644 --- a/tuprolog/core/__init__.py +++ b/tuprolog/core/__init__.py @@ -1,3 +1,5 @@ +from decimal import Decimal + from tuprolog import logger import jpype import jpype.imports @@ -9,7 +11,6 @@ from typing import Iterable, Union, Dict from ._ktmath import * - Atom = _core.Atom Block = _core.Block @@ -86,7 +87,7 @@ def block(*terms: Union[Term, Iterable[Term]]) -> Block: return iterable_or_varargs(terms, lambda ts: Block.of(jiterable(ts))) -def clause(head: Term=None, *body: Union[Term, Iterable[Term]]): +def clause(head: Term = None, *body: Union[Term, Iterable[Term]]): return iterable_or_varargs(body, lambda bs: Clause.of(head, jiterable(bs))) @@ -94,10 +95,10 @@ def empty_logic_list() -> EmptyList: return EmptyList.getInstance() -def cons(head: Term, tail: Term=None) -> Cons: +def cons(head: Term, tail: Term = None) -> Cons: if tail is None: return Cons.singleton(head) - else: + else: return Cons.of(head, tail) @@ -117,38 +118,20 @@ def indicator(name: Union[str, Term], arity: Union[int, Term]) -> Indicator: return Indicator.of(name, arity) -def numeric(value: Union[int, BigInteger, BigDecimal, str, float]) -> Numeric: - if isinstance(value, str): - return Numeric.of(jpype.JString @ value) - if isinstance(value, BigInteger): - return Integer.of(BigInteger @ value) - if isinstance(value, BigDecimal): - return Real.of(BigDecimal @ value) - if isinstance(value, int): - return Integer.of(jpype.JLong @ value) - if isinstance(value, float): - return Real.of(jpype.JDouble @ value) - return Numeric.of(value) +def integer(value: Union[int, BigInteger, str]) -> Integer: + return Integer.of(big_integer(value)) -def integer(value: Union[int, BigInteger, str]) -> Integer: - if isinstance(value, str): - return Integer.of(jpype.JString @ value) - if isinstance(value, BigInteger): - return Integer.of(BigInteger @ value) - if isinstance(value, int): - return Integer.of(jpype.JLong @ value) - return Integer.of(value) +def real(value: Union[float, BigDecimal, str, Decimal]) -> Real: + return Real.of(big_decimal(value)) -def real(value: Union[float, BigDecimal, str]) -> Real: +def numeric(value: Union[int, BigInteger, BigDecimal, str, float, Decimal]) -> Numeric: if isinstance(value, str): - return Real.of(jpype.JString @ value) - if isinstance(value, BigDecimal): - return Real.of(BigDecimal @ value) - if isinstance(value, float): - return Real.of(jpype.JDouble @ value) - return Real.of(value) + return Numeric.of(jpype.JString @ value) + if isinstance(value, int) or isinstance(value, BigInteger): + return integer(value) + return real(value) def rule(head: Struct, *body: Union[Term, Iterable[Term]]) -> Rule: @@ -165,17 +148,19 @@ def truth(boolean: bool) -> Truth: TRUE = Truth.TRUE - FALSE = Truth.FALSE - FAIL = Truth.FAIL -def logic_list(*items: Union[Term, Iterable[Term]]) -> Tuple: +def logic_list(*items: Union[Term, Iterable[Term]]) -> List: return iterable_or_varargs(items, lambda xs: List.of(jiterable(xs))) +def logic_list_from(items: Iterable[Term], last: Term = None) -> List: + return List.from_(jiterable(items), last) + + def logic_tuple(first: Term, second: Term, *others: Union[Term, Iterable[Term]]) -> Tuple: return iterable_or_varargs(others, lambda os: Tuple.of(jiterable([first, second] + list(os)))) @@ -184,11 +169,11 @@ def var(name: str) -> Var: return Var.of(name) -def unifier(assignments: Dict[Var, Term]={}) -> Substitution.Unifier: +def unifier(assignments: Dict[Var, Term] = {}) -> Substitution.Unifier: return Substitution.unifier(jmap(assignments)) -def substitution(assignments: Dict[Var, Term]={}) -> Substitution: +def substitution(assignments: Dict[Var, Term] = {}) -> Substitution: return Substitution.of(jmap(assignments)) @@ -201,4 +186,11 @@ def failed() -> Substitution.Fail: FAILED_SUBSTITUTION: Substitution.Fail = failed() +def scope(*variables: Union[Var, str]) -> Scope: + if len(variables) == 0: + return Scope.empty() + vars = [var(v) if isinstance(v, str) else v for v in variables] + return Scope.of(jpype.JArray(Var) @ vars) + + logger.debug("Loaded JVM classes from it.unibo.tuprolog.core.*") diff --git a/tuprolog/core/_ktadapt.py b/tuprolog/core/_ktadapt.py index 61cb749..39c8556 100644 --- a/tuprolog/core/_ktadapt.py +++ b/tuprolog/core/_ktadapt.py @@ -1,5 +1,9 @@ +from decimal import Decimal + from tuprolog import logger import jpype + +from ._ktmath import big_integer, big_decimal, BigInteger, BigDecimal from tuprolog.utils import * from typing import Sized, Callable from tuprolog.jvmutils import jiterable @@ -421,4 +425,98 @@ def filter(self, filter): return self.filter_(filter) +@jpype.JImplementationFor("it.unibo.tuprolog.core.Scope") +class _KtScope: + def __jclass_init__(cls): + pass + + def __contains__(self, item): + return self.contains(item) + + def __getitem__(self, item): + return self.get(item) + + @property + def variables(self): + return self.getVariables() + + @property + def fail(self): + return self.getFail() + + @property + def empty_list(self): + return self.getEmptyList() + + @property + def empty_block(self): + return self.getEmptyBlock() + + def atom(self, string): + return self.atomOf(string) + + def block(self, *terms): + return iterable_or_varargs(terms, lambda ts: self.blockOf(jiterable(ts))) + + def clause(self, head=None, *body): + return iterable_or_varargs(body, lambda bs: self.clauseOf(head, jiterable(bs))) + + def cons(self, head, tail=None): + if tail is None: + return self.listOf(head) + else: + return self.consOf(head, tail) + + def directive(self, *goals): + return iterable_or_varargs(goals, lambda gs: self.directiveOf(jiterable(gs))) + + def fact(self, head): + return self.factOf(head) + + def indicator(self, name, arity): + return self.indicatorOf(name, arity) + + def integer(self, value): + return self.intOf(big_integer(value)) + + def real(self, value): + return self.intOf(big_integer(value)) + + def numeric(self, value): + if isinstance(value, str): + return self.numOf(value) + if isinstance(value, int) or isinstance(value, BigInteger): + return self.intOf(value) + return self.realOf(value) + + def rule(self, head, *body): + return iterable_or_varargs(body, lambda bs: self.ruleOf(head, jiterable(bs))) + + def struct(self, functor, *args): + return iterable_or_varargs(args, lambda xs: self.structOf(functor, jiterable(xs))) + + def truth(self, value): + return self.truthOf(value) + + def var(self, name): + return self.varOf(name) + + def list(self, *items): + return iterable_or_varargs(items, lambda xs: self.listOf(jiterable(xs))) + + def list_from(self, items, last=None): + return self.listFrom(jiterable(items), last) + + def tuple(self, first, second, *others): + return iterable_or_varargs(others, lambda os: self.tupleOf(jiterable([first, second] + list(os)))) + + @property + def anonymous(self): + return self.getAnonymous() + + @property + def whatever(self): + return self.getWhatever() + + logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.core.*") From 54ceb5d4134d7a5c8a6e0c1506c1ba3b707ede06 Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Tue, 9 Nov 2021 17:50:53 +0100 Subject: [PATCH 012/154] fix horrible bug about integers --- test/core/test_kt_math.py | 10 +++++++++- test/core/test_scope.py | 10 +++++++++- tuprolog/core/__init__.py | 7 ++++++- tuprolog/core/_ktmath.py | 11 ++++++----- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/test/core/test_kt_math.py b/test/core/test_kt_math.py index 6cdea22..1c73305 100644 --- a/test/core/test_kt_math.py +++ b/test/core/test_kt_math.py @@ -3,7 +3,7 @@ from tuprolog.core import big_integer, python_integer, big_decimal, python_decimal, BIG_INTEGER_ZERO, BIG_INTEGER_TEN, \ BIG_INTEGER_ONE, BIG_INTEGER_NEGATIVE_ONE, BIG_INTEGER_TWO, BIG_DECIMAL_PI, BIG_DECIMAL_E, BIG_DECIMAL_ONE_TENTH, \ - BIG_DECIMAL_ONE_HALF, BIG_DECIMAL_ONE, BIG_DECIMAL_ZERO + BIG_DECIMAL_ONE_HALF, BIG_DECIMAL_ONE, BIG_DECIMAL_ZERO, BigInteger class TestKtMath(unittest.TestCase): @@ -48,6 +48,14 @@ def test_constants(self): self.assertEqual(big_integer(-1), BIG_INTEGER_NEGATIVE_ONE) self.assertEqual(big_integer(2), BIG_INTEGER_TWO) + def test_integers(self): + for i in range(-512, 513): + self.assertEqual(BigInteger.of(i), big_integer(i)) + for t in [8, 16, 32, 64, 128]: + for i in [1 << t - 1, 1 << t]: + self.assertEqual(BigInteger.of(str(i)), big_integer(i)) + self.assertEqual(BigInteger.of(str(-i)), big_integer(-i)) + class TestBigDecimal(TestKtMath): diff --git a/test/core/test_scope.py b/test/core/test_scope.py index d81d369..690b3eb 100644 --- a/test/core/test_scope.py +++ b/test/core/test_scope.py @@ -1,5 +1,5 @@ import unittest -from tuprolog.core import scope, var, Scope +from tuprolog.core import scope, var, Scope, variables, struct class TestScope(unittest.TestCase): @@ -18,6 +18,14 @@ def test_scope_creation(self): for v in full_scope.variables: self.assertIn(v, {'A', 'B'}) + def test_variables_reuse(self): + A, B = variables('A', 'B') + s = scope(A, B) + self.assertEqual(A, s['A']) + self.assertEqual(B, s['B']) + fAB = s.struct('f', s.var('A'), s.var('B')) + self.assertEqual(struct('f', A, B), fAB) + if __name__ == '__main__': unittest.main() diff --git a/tuprolog/core/__init__.py b/tuprolog/core/__init__.py index 1b2c56c..296790d 100644 --- a/tuprolog/core/__init__.py +++ b/tuprolog/core/__init__.py @@ -8,7 +8,7 @@ import it.unibo.tuprolog.core as _core from tuprolog.pyutils import iterable_or_varargs from tuprolog.jvmutils import jiterable, jmap -from typing import Iterable, Union, Dict +from typing import Iterable, Dict, Tuple as PyTuple from ._ktmath import * Atom = _core.Atom @@ -193,4 +193,9 @@ def scope(*variables: Union[Var, str]) -> Scope: return Scope.of(jpype.JArray(Var) @ vars) +def variables(*names: str) -> PyTuple[Var]: + assert len(names) > 0 + return tuple((var(n) for n in names)) + + logger.debug("Loaded JVM classes from it.unibo.tuprolog.core.*") diff --git a/tuprolog/core/_ktmath.py b/tuprolog/core/_ktmath.py index 53bb8f6..0265f8b 100644 --- a/tuprolog/core/_ktmath.py +++ b/tuprolog/core/_ktmath.py @@ -49,12 +49,13 @@ BIG_DECIMAL_PI = BigDecimal.PI -def _size_of(n: int) -> int: - return max(ceil(n.bit_length() / 8), 1) - - def _int_to_bytes(n: int) -> bytes: - return n.to_bytes(_size_of(n), 'big', signed=True) + try: + size = n.bit_length() // 8 + 1 + return n.to_bytes(size, 'big', signed=True) + except OverflowError as e: + e.args = ["%s: %d, whose size is %d" % (e.args[0], n, size)] + raise e def big_integer(value: Union[str, int], radix: int = None) -> BigInteger: From 9b3f10e1321729983f02fbeb6c1b7e7e153f9e92 Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Wed, 17 Nov 2021 13:55:09 +0100 Subject: [PATCH 013/154] harmonize java.lang.Throwable --- tuprolog/jvmutils.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tuprolog/jvmutils.py b/tuprolog/jvmutils.py index 2de2aa0..0f3c6d9 100644 --- a/tuprolog/jvmutils.py +++ b/tuprolog/jvmutils.py @@ -209,6 +209,24 @@ def __ge__(self, other): return self.compareTo(other) >= 0 +@jpype.JImplementationFor("java.lang.Throwable") +class _JvmThrowable: + def __jclass_init__(self): + pass + + @property + def message(self): + return self.getMessage() + + @property + def localized_message(self): + return self.getLocalizedMessage() + + @property + def cause(self): + return self.getCause() + + class _KtFunction(Callable): def __init__(self, arity: int, function: Callable): self._function = function From b78b7b794c8cd186162819f38430df5176718a60 Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Wed, 17 Nov 2021 13:55:27 +0100 Subject: [PATCH 014/154] harmonize types in :theory --- tuprolog/theory/__init__.py | 1 + tuprolog/theory/_ktadapt.py | 91 ++++++++++++++++++++++++++++++++++++ tuprolog/theory/parsing.py | 93 ------------------------------------- 3 files changed, 92 insertions(+), 93 deletions(-) create mode 100644 tuprolog/theory/_ktadapt.py delete mode 100644 tuprolog/theory/parsing.py diff --git a/tuprolog/theory/__init__.py b/tuprolog/theory/__init__.py index 19e1ac0..0535e83 100644 --- a/tuprolog/theory/__init__.py +++ b/tuprolog/theory/__init__.py @@ -7,6 +7,7 @@ from tuprolog.core import Clause from tuprolog.pyutils import iterable_or_varargs from tuprolog.jvmutils import jiterable +from ._ktadapt import * Theory = _theory.Theory diff --git a/tuprolog/theory/_ktadapt.py b/tuprolog/theory/_ktadapt.py new file mode 100644 index 0000000..736d4b6 --- /dev/null +++ b/tuprolog/theory/_ktadapt.py @@ -0,0 +1,91 @@ +from tuprolog import logger +import jpype + +from tuprolog.core import indicator as new_indicator +from tuprolog.jvmutils import jiterable +from tuprolog.pyutils import iterable_or_varargs +from typing import Sized + + +@jpype.JImplementationFor("it.unibo.tuprolog.theory.Theory") +class _KtTheory: + def __jclass_init__(cls): + Sized.register(cls) + + @property + def is_mutable(self): + return self.isMutable() + + def to_mutable_theory(self): + return self.toMutableTheory() + + def to_immutable_theory(self): + return self.toImmutableTheory() + + @property + def clauses(self): + return self.getClauses() + + @property + def rules(self): + return self.getRules() + + @property + def directives(self): + return self.getDirectives() + + def __len__(self): + return self.getSize() + + def __add__(self, other): + return self.plus(other) + + def __contains__(self, item): + return self.contains(item) + + def __getitem__(self, item): + return self.get(item) + + def _assert(self, method, clause, *clauses): + if len(clauses) == 0: + return method(clause) + return iterable_or_varargs((clause,) + clauses, lambda cs: method(jiterable(cs))) + + def assert_a(self, clause, *clauses): + self._assert(self.assertA, clause, *clauses) + + def assert_z(self, clause, *clauses): + self._assert(self.assertZ, clause, *clauses) + + @jpype.JOverride + def retract(self, clause, *clauses): + if len(clauses) == 0: + return self.retract_(clause) + return iterable_or_varargs((clause,) + clauses, lambda cs: self.retract_(jiterable(cs))) + + def retract_all(self, clause): + return self.retractAll(clause) + + @jpype.JOverride + def abolish(self, name, arity=None, indicator=None): + if name is not None: + if arity is not None: + return self.abolish_(new_indicator(name, arity)) + else: + return self.abolish_(name) + elif indicator is not None: + return self.abolish_(indicator) + raise ValueError("You should provide at least either a name-arity couple or an indicator") + + @jpype.JOverride + def equals(self, other, use_var_complete_name=True): + return self.equals_(other, use_var_complete_name) + + def __eq__(self, other): + return self.equals(other, use_var_complete_name=True) + + def to_string(self, as_prolog_text=False): + return self.toString(as_prolog_text) + + +logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.theory.*") diff --git a/tuprolog/theory/parsing.py b/tuprolog/theory/parsing.py deleted file mode 100644 index 5c2cb1d..0000000 --- a/tuprolog/theory/parsing.py +++ /dev/null @@ -1,93 +0,0 @@ -from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype -# noinspection PyUnresolvedReferences -import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.theory.parsing as _parsing -from tuprolog.core import Clause -from tuprolog.theory import Theory -from tuprolog.jvmutils import InputStream, ensure_input_steam -from tuprolog.core.operators import OperatorSet, DEFAULT_OPERATORS -from typing import Union, Iterable - - -ClausesParser = _parsing.ClausesParser - -ClausesReader = _parsing.ClausesReader - - -def clauses_parser(with_default_operators: bool = True, operators: OperatorSet = None) -> ClausesParser: - if operators is None: - if with_default_operators: - return ClausesParser.getWithDefaultOperators() - else: - return ClausesParser.getWithNoOperator() - else: - if with_default_operators: - return ClausesParser.withOperators(DEFAULT_OPERATORS.plus(operators)) - else: - return ClausesParser.withOperators(operators) - - -def clauses_reader(with_default_operators: bool = True, operators: OperatorSet = None) -> ClausesReader: - if operators is None: - if with_default_operators: - return ClausesReader.getWithDefaultOperators() - else: - return ClausesReader.getWithNoOperator() - else: - if with_default_operators: - return ClausesReader.withOperators(DEFAULT_OPERATORS.plus(operators)) - else: - return ClausesReader.withOperators(operators) - - -DEFAULT_CLAUSES_PARSER = clauses_parser() - -DEFAULT_CLAUSES_READER = clauses_reader() - - -def parse_theory(string: str, operators: OperatorSet = None) -> Theory: - if operators is None: - return DEFAULT_CLAUSES_PARSER.parseTheory(string) - else: - return DEFAULT_CLAUSES_PARSER.parseTheory(string, operators) - - -def parse_clauses(string: str, operators: OperatorSet = None, lazy: bool = True) -> Iterable[Clause]: - if lazy: - if operators is None: - return DEFAULT_CLAUSES_PARSER.parseClausesLazily(string) - else: - return DEFAULT_CLAUSES_PARSER.parseClausesLazily(string, operators) - else: - if operators is None: - return DEFAULT_CLAUSES_PARSER.parseClauses(string) - else: - return DEFAULT_CLAUSES_PARSER.parseClauses(string, operators) - - -def read_theory(input: Union[InputStream, str], operators: OperatorSet = None) -> Theory: - input = ensure_input_steam(input) - if operators is None: - return DEFAULT_CLAUSES_READER.readTheory(input) - else: - return DEFAULT_CLAUSES_READER.readTheory(input, operators) - - -def read_clauses(input: Union[InputStream, str], operators: OperatorSet = None, lazy: bool = True) -> Iterable[Clause]: - input = ensure_input_steam(input) - if lazy: - if operators is None: - return DEFAULT_CLAUSES_READER.readClausesLazily(input) - else: - return DEFAULT_CLAUSES_READER.readClausesLazily(input, operators) - else: - if operators is None: - return DEFAULT_CLAUSES_READER.readClauses(input) - else: - return DEFAULT_CLAUSES_READER.readClauses(input, operators) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.theory.parsing.*") From 654b8fdeb60109f624d4f0beda6aa17051fed797 Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Wed, 17 Nov 2021 13:55:44 +0100 Subject: [PATCH 015/154] harmonize types in :parser-core --- tuprolog/core/parsing.py | 132 ------------------------------ tuprolog/core/parsing/__init__.py | 91 ++++++++++++++++++++ tuprolog/core/parsing/_ktadapt.py | 82 +++++++++++++++++++ 3 files changed, 173 insertions(+), 132 deletions(-) delete mode 100644 tuprolog/core/parsing.py create mode 100644 tuprolog/core/parsing/__init__.py create mode 100644 tuprolog/core/parsing/_ktadapt.py diff --git a/tuprolog/core/parsing.py b/tuprolog/core/parsing.py deleted file mode 100644 index b19977a..0000000 --- a/tuprolog/core/parsing.py +++ /dev/null @@ -1,132 +0,0 @@ -from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.core.parsing as _parsing -from tuprolog.core import Term, Struct, Constant, Var, Atom, Numeric, Integer, Real, Clause -from tuprolog.jvmutils import InputStream - -TermParser = _parsing.TermParser - -TermReader = _parsing.TermReader - -ParseException = _parsing.ParseException - -InvalidTermTypeException = _parsing.InvalidTermTypeException - -from tuprolog.core.operators import Operator, OperatorSet, DEFAULT_OPERATORS, EMPTY_OPERATORS - -from typing import Union, Iterable - - -def term_parser(with_default_operators: bool=True, operators: OperatorSet=None) -> TermParser: - if operators is None: - if with_default_operators: - return TermParser.getWithDefaultOperators() - else: - return TermParser.getWithNoOperator() - else: - if with_default_operators: - return TermParser.withOperators(DEFAULT_OPERATORS.plus(operators)) - else: - return TermParser.withOperators(operators) - - -def term_reader(with_default_operators: bool=True, operators: OperatorSet=None) -> TermParser: - if operators is None: - if with_default_operators: - return TermReader.getWithDefaultOperators() - else: - return TermReader.getWithNoOperator() - else: - if with_default_operators: - return TermReader.withOperators(DEFAULT_OPERATORS.plus(operators)) - else: - return TermReader.withOperators(operators) - - -DEFAULT_TERM_PARSER = term_parser() - -DEFAULT_TERM_READER = term_reader() - - -def parse_term(string: str, operators: OperatorSet=None) -> Term: - if operators is None: - return DEFAULT_TERM_PARSER.parseTerm(string) - else: - return DEFAULT_TERM_PARSER.parseTerm(string, operators) - - -def parse_struct(string: str, operators: OperatorSet=None) -> Struct: - if operators is None: - return DEFAULT_TERM_PARSER.parseStruct(string) - else: - return DEFAULT_TERM_PARSER.parseStruct(string, operators) - - -def parse_constant(string: str, operators: OperatorSet=None) -> Constant: - if operators is None: - return DEFAULT_TERM_PARSER.parseConstant(string) - else: - return DEFAULT_TERM_PARSER.parseConstant(string, operators) - - -def parse_var(string: str, operators: OperatorSet=None) -> Var: - if operators is None: - return DEFAULT_TERM_PARSER.parseVar(string) - else: - return DEFAULT_TERM_PARSER.parseVar(string, operators) - - -def parse_atom(string: str, operators: OperatorSet=None) -> Atom: - if operators is None: - return DEFAULT_TERM_PARSER.parseAtom(string) - else: - return DEFAULT_TERM_PARSER.parseAtom(string, operators) - - -def parse_numeric(string: str, operators: OperatorSet=None) -> Numeric: - if operators is None: - return DEFAULT_TERM_PARSER.parseNumeric(string) - else: - return DEFAULT_TERM_PARSER.parseNumeric(string, operators) - - -def parse_integer(string: str, operators: OperatorSet=None) -> Integer: - if operators is None: - return DEFAULT_TERM_PARSER.parseInteger(string) - else: - return DEFAULT_TERM_PARSER.parseInteger(string, operators) - - -def parse_real(string: str, operators: OperatorSet=None) -> Real: - if operators is None: - return DEFAULT_TERM_PARSER.parseReal(string) - else: - return DEFAULT_TERM_PARSER.parseReal(string, operators) - - -def parse_clause(string: str, operators: OperatorSet=None) -> Clause: - if operators is None: - return DEFAULT_TERM_PARSER.parseClause(string) - else: - return DEFAULT_TERM_PARSER.parseClause(string, operators) - - -def read_term(input: Union[InputStream, str], operators: OperatorSet=None) -> Term: - input = ensure_input_steam(input) - if operators is None: - return DEFAULT_TERM_READER.readTerm(input) - else: - return DEFAULT_TERM_READER.readTerm(input, operators) - - -def read_terms(input: Union[InputStream, str], operators: OperatorSet=None) -> Iterable[Term]: - input = ensure_input_steam(input) - if operators is None: - return DEFAULT_TERM_READER.readTerms(input) - else: - return DEFAULT_TERM_READER.readTerms(input, operators) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.core.parsing.*") diff --git a/tuprolog/core/parsing/__init__.py b/tuprolog/core/parsing/__init__.py new file mode 100644 index 0000000..9f68211 --- /dev/null +++ b/tuprolog/core/parsing/__init__.py @@ -0,0 +1,91 @@ +from tuprolog import logger +# noinspection PyUnresolvedReferences +import jpype.imports +# noinspection PyUnresolvedReferences +import it.unibo.tuprolog.core.parsing as _parsing +from tuprolog.core import Term, Struct, Constant, Var, Atom, Numeric, Integer, Real, Clause +from tuprolog.jvmutils import InputStream +from tuprolog.core.operators import OperatorSet, DEFAULT_OPERATORS +from typing import Union, Iterable +from ._ktadapt import * + +TermParser = _parsing.TermParser + +TermReader = _parsing.TermReader + +ParseException = _parsing.ParseException + +InvalidTermTypeException = _parsing.InvalidTermTypeException + + +def _factory(source, with_default_operators: bool = True, operators: OperatorSet = None): + if operators is None: + if with_default_operators: + return source.getWithDefaultOperators() + else: + return source.getWithNoOperator() + else: + if with_default_operators: + return source.withOperators(DEFAULT_OPERATORS.plus(operators)) + else: + return source.withOperators(operators) + + +def term_parser(with_default_operators: bool = True, operators: OperatorSet = None) -> TermParser: + return _factory(TermParser, with_default_operators, operators) + + +def term_reader(with_default_operators: bool = True, operators: OperatorSet = None) -> TermParser: + return _factory(TermReader, with_default_operators, operators) + + +DEFAULT_TERM_PARSER = term_parser() + +DEFAULT_TERM_READER = term_reader() + + +def parse_term(string: str, operators: OperatorSet = None) -> Term: + return DEFAULT_TERM_PARSER.parse_term(string, operators) + + +def parse_struct(string: str, operators: OperatorSet = None) -> Struct: + return DEFAULT_TERM_PARSER.parse_struct(string, operators) + + +def parse_constant(string: str, operators: OperatorSet = None) -> Constant: + return DEFAULT_TERM_PARSER.parse_constant(string, operators) + + +def parse_var(string: str, operators: OperatorSet = None) -> Var: + return DEFAULT_TERM_PARSER.parse_var(string, operators) + + +def parse_atom(string: str, operators: OperatorSet = None) -> Atom: + return DEFAULT_TERM_PARSER.parse_atom(string, operators) + + +def parse_numeric(string: str, operators: OperatorSet = None) -> Numeric: + return DEFAULT_TERM_PARSER.parse_numeric(string, operators) + + +def parse_integer(string: str, operators: OperatorSet = None) -> Integer: + return DEFAULT_TERM_PARSER.parse_integer(string, operators) + + +def parse_real(string: str, operators: OperatorSet = None) -> Real: + return DEFAULT_TERM_PARSER.parse_real(string, operators) + + +def parse_clause(string: str, operators: OperatorSet = None) -> Clause: + return DEFAULT_TERM_PARSER.parse_clause(string, operators) + + +def read_term(input: Union[InputStream, str], operators: OperatorSet = None) -> Term: + return DEFAULT_TERM_READER.read_term(input, operators) + + +def read_terms(input: Union[InputStream, str], operators: OperatorSet = None) -> Iterable[Term]: + return DEFAULT_TERM_READER.read_terms(input, operators) + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.core.parsing.*") diff --git a/tuprolog/core/parsing/_ktadapt.py b/tuprolog/core/parsing/_ktadapt.py new file mode 100644 index 0000000..046b218 --- /dev/null +++ b/tuprolog/core/parsing/_ktadapt.py @@ -0,0 +1,82 @@ +from tuprolog import logger +import jpype + +from tuprolog.jvmioutils import ensure_input_steam + + +@jpype.JImplementationFor("it.unibo.tuprolog.core.parsing.TermParser") +class _KtTermParser: + def __jclass_init__(cls): + pass + + @property + def default_operator_set(self): + return self.getDefaultOperatorSet() + + def _parse(self, method, input, operators): + if operators is None: + return method(input) + else: + return method(input, operators) + + def parse(self, input, operators=None): + return self.parse_term(input, operators) + + def parse_term(self, input, operators=None): + return self._parse(self.parseTerm, input, operators) + + def parse_struct(self, input, operators=None): + return self._parse(self.parseStruct, input, operators) + + def parse_constant(self, input, operators=None): + return self._parse(self.parseConstant, input, operators) + + def parse_var(self, input, operators=None): + return self._parse(self.parseVar, input, operators) + + def parse_atom(self, input, operators=None): + return self._parse(self.parseAtom, input, operators) + + def parse_numeric(self, input, operators=None): + return self._parse(self.parseNumeric, input, operators) + + def parse_integer(self, input, operators=None): + return self._parse(self.parseInteger, input, operators) + + def parse_real(self, input, operators=None): + return self._parse(self.parseReal, input, operators) + + def parse_clause(self, input, operators=None): + return self._parse(self.parseClause, input, operators) + + +@jpype.JImplementationFor("it.unibo.tuprolog.core.parsing.TermReader") +class _KtTermReader: + def __jclass_init__(cls): + pass + + @property + def default_operator_set(self): + return self.getDefaultOperatorSet() + + def _read(self, method, input, operators): + input_stream = ensure_input_steam(input) + if operators is None: + return method(input_stream) + else: + return method(input_stream, operators) + + def read(self, input, operators=None): + return self.read_term(input, operators) + + def read_term(self, input, operators=None): + return self._read(self.readTerm, input, operators) + + def read_all(self, input, operators=None): + return self.read_terms(input, operators) + + def read_terms(self, input, operators=None): + return self._read(self.readTerms, input, operators) + + +logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.core.parsing.*") From fb315fc3332b9dbd3a73c2aa24195f4eed00febf Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Wed, 17 Nov 2021 13:55:52 +0100 Subject: [PATCH 016/154] harmonize types in :parser-theory --- tuprolog/theory/parsing/__init__.py | 57 ++++++++++++++++++++++++++++ tuprolog/theory/parsing/_ktadapt.py | 59 +++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 tuprolog/theory/parsing/__init__.py create mode 100644 tuprolog/theory/parsing/_ktadapt.py diff --git a/tuprolog/theory/parsing/__init__.py b/tuprolog/theory/parsing/__init__.py new file mode 100644 index 0000000..ece0c7e --- /dev/null +++ b/tuprolog/theory/parsing/__init__.py @@ -0,0 +1,57 @@ +from tuprolog import logger +# noinspection PyUnresolvedReferences +import jpype +# noinspection PyUnresolvedReferences +import jpype.imports +# noinspection PyUnresolvedReferences +import it.unibo.tuprolog.theory.parsing as _parsing +from tuprolog.core import Clause +from tuprolog.core.parsing import _factory +from tuprolog.theory import Theory +from tuprolog.jvmutils import InputStream +from tuprolog.core.operators import OperatorSet +from typing import Union, Iterable +from ._ktadapt import * + + +ClausesParser = _parsing.ClausesParser + +ClausesReader = _parsing.ClausesReader + + +def clauses_parser(with_default_operators: bool = True, operators: OperatorSet = None) -> ClausesParser: + return _factory(ClausesParser, with_default_operators, operators) + + +def clauses_reader(with_default_operators: bool = True, operators: OperatorSet = None) -> ClausesReader: + return _factory(ClausesReader, with_default_operators, operators) + + +DEFAULT_CLAUSES_PARSER = clauses_parser() + +DEFAULT_CLAUSES_READER = clauses_reader() + + +def parse_theory(string: str, operators: OperatorSet = None) -> Theory: + return DEFAULT_CLAUSES_PARSER.parse_theory(string, operators) + + +def parse_clauses(string: str, operators: OperatorSet = None, lazy: bool = True) -> Iterable[Clause]: + if lazy: + return DEFAULT_CLAUSES_PARSER.parse_clauses_lazily(string, operators) + else: + return DEFAULT_CLAUSES_PARSER.parse_clauses(string, operators) + + +def read_theory(input: Union[InputStream, str], operators: OperatorSet = None) -> Theory: + return DEFAULT_CLAUSES_READER.read_theory(input, operators) + + +def read_clauses(input: Union[InputStream, str], operators: OperatorSet = None, lazy: bool = True) -> Iterable[Clause]: + if lazy: + return DEFAULT_CLAUSES_READER.read_clauses_lazily(input, operators) + else: + return DEFAULT_CLAUSES_READER.read_clauses(input, operators) + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.theory.parsing.*") diff --git a/tuprolog/theory/parsing/_ktadapt.py b/tuprolog/theory/parsing/_ktadapt.py new file mode 100644 index 0000000..2456d97 --- /dev/null +++ b/tuprolog/theory/parsing/_ktadapt.py @@ -0,0 +1,59 @@ +from tuprolog import logger +import jpype + +from tuprolog.jvmioutils import ensure_input_steam + + +@jpype.JImplementationFor("it.unibo.tuprolog.theory.parsing.ClausesParser") +class _KtClausesParser: + def __jclass_init__(cls): + pass + + @property + def default_operator_set(self): + return self.getDefaultOperatorSet() + + def _parse(self, method, input, operators): + if operators is None: + return method(input) + else: + return method(input, operators) + + def parse_theory(self, input, operators): + return self._parse(self.parseTheory, input, operators) + + def parse_clauses_lazily(self, input, operators): + return self._parse(self.parseClausesLazily, input, operators) + + def parse_clauses(self, input, operators): + return list(self.parse_clauses_lazily(input, operators)) + + + +@jpype.JImplementationFor("it.unibo.tuprolog.theory.parsing.ClausesReader") +class _KtClausesReader: + def __jclass_init__(cls): + pass + + @property + def default_operator_set(self): + return self.getDefaultOperatorSet() + + def _read(self, method, input, operators): + input_stream = ensure_input_steam(input) + if operators is None: + return method(input_stream) + else: + return method(input_stream, operators) + + def read_theory(self, input, operators): + return self._read(self.readTheory, input, operators) + + def read_clauses_lazily(self, input, operators): + return self._read(self.readClausesLazily, input, operators) + + def read_clauses(self, input, operators): + return list(self.read_clauses_lazily(input, operators)) + + +logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.theory.parsing.*") From e8792299743cadc8f3da1391fdf5811953cba0c6 Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Wed, 17 Nov 2021 14:36:28 +0100 Subject: [PATCH 017/154] harmonize exception types in :core --- tuprolog/__init__.py | 4 ++- tuprolog/__main__.py | 3 ++- .../{exception.py => exception/__init__.py} | 3 +-- tuprolog/core/exception/_ktadapt.py | 25 +++++++++++++++++++ tuprolog/core/operators/_ktadapt.py | 4 +++ 5 files changed, 35 insertions(+), 4 deletions(-) rename tuprolog/core/{exception.py => exception/__init__.py} (94%) create mode 100644 tuprolog/core/exception/_ktadapt.py diff --git a/tuprolog/__init__.py b/tuprolog/__init__.py index c8de217..024eefd 100644 --- a/tuprolog/__init__.py +++ b/tuprolog/__init__.py @@ -14,7 +14,9 @@ jpype.startJVM(classpath=jars) # noinspection PyUnresolvedReferences -from it.unibo.tuprolog import Info +from it.unibo import tuprolog as _tuprolog + +Info = _tuprolog.Info JVM_VERSION = '.'.join(map(str, jpype.getJVMVersion())) diff --git a/tuprolog/__main__.py b/tuprolog/__main__.py index b6f61fc..e487d52 100644 --- a/tuprolog/__main__.py +++ b/tuprolog/__main__.py @@ -7,6 +7,7 @@ from tuprolog.core.visitors import * from tuprolog.core.parsing import * from tuprolog.unify import * +from tuprolog.unify.exception import * from tuprolog.theory import * from tuprolog.theory.parsing import * from tuprolog.solve import * @@ -35,4 +36,4 @@ code.interact(local=locals()) -input() \ No newline at end of file +input() diff --git a/tuprolog/core/exception.py b/tuprolog/core/exception/__init__.py similarity index 94% rename from tuprolog/core/exception.py rename to tuprolog/core/exception/__init__.py index cba30b7..65d044a 100644 --- a/tuprolog/core/exception.py +++ b/tuprolog/core/exception/__init__.py @@ -1,10 +1,9 @@ from tuprolog import logger - # noinspection PyUnresolvedReferences import jpype.imports - # noinspection PyUnresolvedReferences import it.unibo.tuprolog.core.exception as _exceptions +from ._ktadapt import * TuPrologException = _exceptions.TuPrologException diff --git a/tuprolog/core/exception/_ktadapt.py b/tuprolog/core/exception/_ktadapt.py new file mode 100644 index 0000000..c43369a --- /dev/null +++ b/tuprolog/core/exception/_ktadapt.py @@ -0,0 +1,25 @@ +from tuprolog import logger +import jpype + + +@jpype.JImplementationFor("it.unibo.tuprolog.core.exception.SubstitutionException") +class _KtSubstitutionException: + def __jclass_init__(cls): + pass + + @property + def substitution(self): + return self.getSubstitution() + + +@jpype.JImplementationFor("it.unibo.tuprolog.core.exception.SubstitutionApplicationException") +class _KtSubstitutionApplicationException: + def __jclass_init__(cls): + pass + + @property + def term(self): + return self.getTerm() + + +logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.core.exception.*") diff --git a/tuprolog/core/operators/_ktadapt.py b/tuprolog/core/operators/_ktadapt.py index 9fdac4d..14edd32 100644 --- a/tuprolog/core/operators/_ktadapt.py +++ b/tuprolog/core/operators/_ktadapt.py @@ -1,3 +1,4 @@ +from tuprolog import logger import jpype @@ -29,3 +30,6 @@ def __add__(self, other): def __sub__(self, other): return self.minus(other) + + +logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.core.operators.*") From 983ce7ccd8c47bd4d65acbc029187ab3c2cd538c Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Wed, 17 Nov 2021 14:36:58 +0100 Subject: [PATCH 018/154] harmonize exception types in :unify --- tuprolog/{unify.py => unify/__init__.py} | 0 tuprolog/unify/exception/__init__.py | 14 ++++++++++++++ tuprolog/unify/exception/_ktadapt.py | 19 +++++++++++++++++++ 3 files changed, 33 insertions(+) rename tuprolog/{unify.py => unify/__init__.py} (100%) create mode 100644 tuprolog/unify/exception/__init__.py create mode 100644 tuprolog/unify/exception/_ktadapt.py diff --git a/tuprolog/unify.py b/tuprolog/unify/__init__.py similarity index 100% rename from tuprolog/unify.py rename to tuprolog/unify/__init__.py diff --git a/tuprolog/unify/exception/__init__.py b/tuprolog/unify/exception/__init__.py new file mode 100644 index 0000000..18f1ec9 --- /dev/null +++ b/tuprolog/unify/exception/__init__.py @@ -0,0 +1,14 @@ +from tuprolog import logger +# noinspection PyUnresolvedReferences +import jpype.imports +# noinspection PyUnresolvedReferences +import it.unibo.tuprolog.unify.exception as _exceptions +from ._ktadapt import * + + +NoUnifyException = _exceptions.NoUnifyException + +OccurCheckException = _exceptions.OccurCheckException + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.unify.exception.*") diff --git a/tuprolog/unify/exception/_ktadapt.py b/tuprolog/unify/exception/_ktadapt.py new file mode 100644 index 0000000..c04f1d3 --- /dev/null +++ b/tuprolog/unify/exception/_ktadapt.py @@ -0,0 +1,19 @@ +from tuprolog import logger +import jpype + + +@jpype.JImplementationFor("it.unibo.tuprolog.unify.exception.NoUnifyException") +class _KtNoUnifyException: + def __jclass_init__(cls): + pass + + @property + def term1(self): + return self.getTerm1() + + @property + def term2(self): + return self.getTerm2() + + +logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.unify.exception.*") From 6f5e9fa36da3be603dcad640358eb4f170dfc47e Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Wed, 17 Nov 2021 15:04:56 +0100 Subject: [PATCH 019/154] + harmonizing types refinement in :unify --- tuprolog/unify/__init__.py | 1 + tuprolog/unify/_ktadapt.py | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 tuprolog/unify/_ktadapt.py diff --git a/tuprolog/unify/__init__.py b/tuprolog/unify/__init__.py index c50e649..d7df192 100644 --- a/tuprolog/unify/__init__.py +++ b/tuprolog/unify/__init__.py @@ -4,6 +4,7 @@ # noinspection PyUnresolvedReferences import it.unibo.tuprolog.unify as _unify from tuprolog.core import Term, Substitution +from ._ktadapt import * Unificator = _unify.Unificator diff --git a/tuprolog/unify/_ktadapt.py b/tuprolog/unify/_ktadapt.py new file mode 100644 index 0000000..69a83db --- /dev/null +++ b/tuprolog/unify/_ktadapt.py @@ -0,0 +1,15 @@ +from tuprolog import logger +import jpype + + +@jpype.JImplementationFor("it.unibo.tuprolog.unify.Unificator") +class _KtUnificator: + def __jclass_init__(cls): + pass + + @property + def context(self): + return self.getContext() + + +logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.unify.*") From b88a394d2e58c9e5bc53dc708db5f6dacb84b0c0 Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Wed, 17 Nov 2021 15:05:06 +0100 Subject: [PATCH 020/154] + harmonizing types refinement in :theory --- tuprolog/jvmutils.py | 6 +++++- tuprolog/theory/__init__.py | 2 -- tuprolog/theory/_ktadapt.py | 41 +++++++++++++++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/tuprolog/jvmutils.py b/tuprolog/jvmutils.py index 0f3c6d9..c98c344 100644 --- a/tuprolog/jvmutils.py +++ b/tuprolog/jvmutils.py @@ -50,6 +50,10 @@ PyUtils = _tuprolog_utils.PyUtils +def protect_iterable(iterable: Iterable) -> Iterable: + return PyUtils.iterable(iterable) + + @jpype.JImplements("java.util.Iterator", deferred=True) class _IteratorAdapter(object): def __init__(self, iterator): @@ -170,7 +174,7 @@ def __jclass_init__(self): PyIterable.register(self) def __iter__(self): - return PyUtils.iterable(self).iterator() + return protect_iterable(self).iterator() def ksequence(iterable: PyIterable) -> Sequence: diff --git a/tuprolog/theory/__init__.py b/tuprolog/theory/__init__.py index 0535e83..81a7c2a 100644 --- a/tuprolog/theory/__init__.py +++ b/tuprolog/theory/__init__.py @@ -5,8 +5,6 @@ import it.unibo.tuprolog.theory as _theory from typing import Iterable, Union from tuprolog.core import Clause -from tuprolog.pyutils import iterable_or_varargs -from tuprolog.jvmutils import jiterable from ._ktadapt import * Theory = _theory.Theory diff --git a/tuprolog/theory/_ktadapt.py b/tuprolog/theory/_ktadapt.py index 736d4b6..6273dfd 100644 --- a/tuprolog/theory/_ktadapt.py +++ b/tuprolog/theory/_ktadapt.py @@ -1,8 +1,7 @@ from tuprolog import logger import jpype - from tuprolog.core import indicator as new_indicator -from tuprolog.jvmutils import jiterable +from tuprolog.jvmutils import jiterable, protect_iterable from tuprolog.pyutils import iterable_or_varargs from typing import Sized @@ -22,14 +21,26 @@ def to_mutable_theory(self): def to_immutable_theory(self): return self.toImmutableTheory() + @jpype.JOverride + def getClauses(self): + return protect_iterable(self.getClauses_()) + @property def clauses(self): return self.getClauses() + @jpype.JOverride + def getRules(self): + return protect_iterable(self.getRules_()) + @property def rules(self): return self.getRules() + @jpype.JOverride + def getDirectives(self): + return protect_iterable(self.getDirectives_()) + @property def directives(self): return self.getDirectives() @@ -88,4 +99,30 @@ def to_string(self, as_prolog_text=False): return self.toString(as_prolog_text) +@jpype.JImplementationFor("it.unibo.tuprolog.theory.RetractResult") +class _KtRetractResult: + def __jclass_init__(cls): + pass + + @property + def is_success(self): + return self.isSuccess() + + @property + def is_failure(self): + return self.isFailure() + + @property + def theory(self): + return self.getTheory() + + @property + def clauses(self): + return self.getClauses() + + @property + def first_clause(self): + return self.getFirstClause() + + logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.theory.*") From 55609415102f8116165a42c8e33e029c4906e160 Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Thu, 25 Nov 2021 18:31:04 +0100 Subject: [PATCH 021/154] harmonize some classes in :solve --- tuprolog/solve/_ktadapt.py | 213 +++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) diff --git a/tuprolog/solve/_ktadapt.py b/tuprolog/solve/_ktadapt.py index 8a21f73..3854fc1 100644 --- a/tuprolog/solve/_ktadapt.py +++ b/tuprolog/solve/_ktadapt.py @@ -1,8 +1,13 @@ +from collections import Mapping +from itertools import chain + from tuprolog import logger # noinspection PyUnresolvedReferences import jpype +from tuprolog.pyutils import iterable_or_varargs + @jpype.JImplementationFor("it.unibo.tuprolog.solve.SolverFactory") class _KtSolverFactory: @@ -10,6 +15,214 @@ def __jclass_init__(self): pass +@jpype.JImplementationFor("it.unibo.tuprolog.solve.SolveOptions") +class _KtSolveOptions: + + _static_keys = {'lazy', 'is_lazy', 'eager', 'is_eager', 'timeout', 'limit'} + + def __jclass_init__(self): + Mapping.register(self) + + @property + def is_lazy(self): + return self.isLazy() + + @property + def is_eager(self): + return self.isEager() + + @property + def timeout(self): + return self.getTimeout() + + @property + def limit(self): + return self.getLimit() + + @property + def options(self): + return self.getOptions() + + def __len__(self): + return 4 + len(self.options) + + def __iter__(self): + return chain(_KtSolveOptions._static_keys, self.options) + + def __contains__(self, item): + return item in _KtSolveOptions._static_keys + + def __getitem__(self, item, default=None): + if item in {'lazy', 'is_lazy'}: + return self.is_lazy + elif item in {'eager', 'is_eager'}: + return self.is_eager + elif item == 'timeout': + return self.timeout + elif item == 'limit': + return self.limit + elif item in self.options: + return self.options[item] + elif default is not None: + return default + return KeyError(f"No such option: {item}") + + +@jpype.JImplementationFor("it.unibo.tuprolog.solve.ExecutionContextAware") +class _KtExecutionContextAware: + def __jclass_init__(self): + pass + + @property + def libraries(self): + return self.getLibraries() + + @property + def flags(self): + return self.getFlags() + + @property + def static_kb(self): + return self.getStaticKb() + + @property + def dynamic_kb(self): + return self.getDynamicKb() + + @property + def operators(self): + return self.getOperators() + + @property + def input_channels(self): + return self.getInputChannles() + + @property + def output_channels(self): + return self.getOutputChannles() + + @property + def standard_output(self): + return self.getStandardOutput() + + @property + def standard_input(self): + return self.getStandardInput() + + @property + def standard_error(self): + return self.getStandardError() + + @property + def warnings(self): + return self.getWarnings() + + +@jpype.JImplementationFor("it.unibo.tuprolog.solve.Solver") +class _KtSolver: + def __jclass_init__(self): + pass + + @jpype.JOverride + def solve(self, goal, options=None): + if options is None: + return self.solve_(goal) + elif options.is_eager: + return self.solveList(goal, options) + else: + return self.solve_(goal, options) + + @jpype.JOverride + def solve_once(self, goal, options=None): + if options is None: + return self.solveOnce(goal) + else: + return self.solveOnce(goal, options) + + +@jpype.JImplementationFor("it.unibo.tuprolog.solve.MutableSolver") +class _KtMutableSolver: + def __jclass_init__(self): + pass + + def load_library(self, library): + return self.loadLibrary(library) + + def unload_library(self, library): + return self.unloadLibrary(library) + + def set_libraries(self, libraries): + return self.setLibraries(libraries) + + def load_static_kb(self, theory): + return self.loadStaticKb(theory) + + def load_static_clauses(self, *clauses): + return iterable_or_varargs(clauses, lambda cs: self.loadStaticClauses(cs)) + + def append_static_kb(self, theory): + return self.appendStaticKb(theory) + + def reset_static_kb(self): + return self.resetStaticKb() + + def load_dynamic_kb(self, theory): + return self.loadDynamicKb(theory) + + def load_dynamic_clauses(self, *clauses): + return iterable_or_varargs(clauses, lambda cs: self.loadDynamicClauses(cs)) + + def append_dynamic_kb(self, theory): + return self.appendDynamicKb(theory) + + def reset_dynamic_kb(self): + return self.resetDynamicKb() + + def assert_a(self, clause): + return self.assertA(clause) + + def assert_z(self, clause): + return self.assertZ(clause) + + def retract_all(self, clause): + return self.retractAll(clause) + + def set_flag(self, *args): + return self.setFlag(*args) + + @property + def standard_output(self): + return self.getStandardOutput() + + @property + def standard_input(self): + return self.getStandardInput() + + @property + def standard_error(self): + return self.getStandardError() + + @property + def warnings(self): + return self.getWarnings() + + @standard_input.setter + def standard_input(self, channel): + return self.setStandardInput(channel) + + @standard_output.setter + def standard_output(self, channel): + return self.setStandardOutput(channel) + + @standard_error.setter + def standard_error(self, channel): + return self.setStandardError(channel) + + @warnings.setter + def warnings(self, channel): + return self.setWarnings(channel) + + @jpype.JImplementationFor("it.unibo.tuprolog.solve.Solution") class _KtSolution: def __jclass_init__(self): From 99b0e4017eaf4780506309962c99d15c788794b9 Mon Sep 17 00:00:00 2001 From: DavideEva <56042077+DavideEva@users.noreply.github.com> Date: Wed, 22 Dec 2021 01:31:03 +0100 Subject: [PATCH 022/154] Removed recursive method invocation Removed recursive method invocation in `tuprolog.core._ktadapt.py` for property is_integer --- tuprolog/core/_ktadapt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tuprolog/core/_ktadapt.py b/tuprolog/core/_ktadapt.py index 39c8556..1da2142 100644 --- a/tuprolog/core/_ktadapt.py +++ b/tuprolog/core/_ktadapt.py @@ -64,7 +64,7 @@ def is_number(self): @property def is_integer(self): - return self.is_integer() + return self.isInteger() @property def is_real(self): From dffd133feee05dae7def627453fbd03b16fb247d Mon Sep 17 00:00:00 2001 From: Giovanni Ciatto Date: Sun, 2 Jan 2022 09:33:20 +0100 Subject: [PATCH 023/154] address #17 - `Numeric.decimal_value` now returns a `decimal` - Add method `Numeric.to_float` --- tuprolog/core/__init__.py | 2 +- tuprolog/core/_ktadapt.py | 33 +++++++++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/tuprolog/core/__init__.py b/tuprolog/core/__init__.py index 296790d..4724b03 100644 --- a/tuprolog/core/__init__.py +++ b/tuprolog/core/__init__.py @@ -9,7 +9,7 @@ from tuprolog.pyutils import iterable_or_varargs from tuprolog.jvmutils import jiterable, jmap from typing import Iterable, Dict, Tuple as PyTuple -from ._ktmath import * + Atom = _core.Atom diff --git a/tuprolog/core/_ktadapt.py b/tuprolog/core/_ktadapt.py index 1da2142..95e12fa 100644 --- a/tuprolog/core/_ktadapt.py +++ b/tuprolog/core/_ktadapt.py @@ -1,14 +1,13 @@ from decimal import Decimal - from tuprolog import logger import jpype - from ._ktmath import big_integer, big_decimal, BigInteger, BigDecimal from tuprolog.utils import * from typing import Sized, Callable from tuprolog.jvmutils import jiterable from tuprolog.pyutils import iterable_or_varargs from tuprolog.jvmutils import kfunction +from ._ktmath import * @jpype.JImplementationFor("it.unibo.tuprolog.core.Term") @@ -216,11 +215,37 @@ def __jclass_init__(cls): @property def int_value(self): - return self.getIntValue() + return python_integer(self.getIntValue()) @property def decimal_value(self): - return self.getDecimalValue() + return python_decimal(self.getDecimalValue()) + + def to_int(self): + return self.int_value + + def to_float(self): + return float(self.decimal_value) + + +@jpype.JImplementationFor("it.unibo.tuprolog.core.Integer") +class _KtInteger: + def __jclass_init__(cls): + pass + + @property + def value(self): + return self.int_value + + +@jpype.JImplementationFor("it.unibo.tuprolog.core.Real") +class _KtReal: + def __jclass_init__(cls): + pass + + @property + def value(self): + return self.decimal_value @jpype.JImplementationFor("it.unibo.tuprolog.core.Recursive") From a44f290e9222d50d702bb4a1408d4611d157cbd6 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 29 Mar 2023 14:26:56 +0200 Subject: [PATCH 024/154] Start working on 2ppy refactor --- .github/dependabot.yml | 11 +++++ .python-version | 2 +- MANIFEST.in | 4 +- pom.xml | 14 ++++++ pyproject.toml | 44 +++++++++++++++++- requirements.txt | 4 +- setup.py | 102 +++++++---------------------------------- 7 files changed, 87 insertions(+), 94 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 pom.xml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..56da085 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 + +updates: + - directory: / + package-ecosystem: pip + schedule: + interval: daily + - directory: / + package-ecosystem: maven + schedule: + interval: daily diff --git a/.python-version b/.python-version index 1635d0f..371cfe3 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.9.6 +3.11.1 diff --git a/MANIFEST.in b/MANIFEST.in index 29ed537..918337f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ -include VERSION +include pom.xml include tuprolog/libs/*.jar exclude test/* -exclude main.py \ No newline at end of file +exclude main.py diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..78268ce --- /dev/null +++ b/pom.xml @@ -0,0 +1,14 @@ + + 4.0.0 + + com.mycompany.app + my-app + 1 + + + it.unibo.tuprolog + repl-jvm + 0.31.1-dev02+0cd8a1ae6 + + + diff --git a/pyproject.toml b/pyproject.toml index 07de284..4bed5d5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,43 @@ [build-system] -requires = ["setuptools", "wheel"] -build-backend = "setuptools.build_meta" \ No newline at end of file +requires = ["setuptools>=61", "wheel", "setuptools-git-versioning<2"] +build-backend = "setuptools.build_meta" + +[tool.setuptools-git-versioning] +enabled = true + +[project] +dynamic = ["version"] +name = "2ppy" +authors = [ + { name="Giovanni Ciatto", email="giovanni.ciatto@unibo.it" }, +] +description = "Python-based implementation of tuProlog -- the open ecosystem for symbolic AI --, based on 2P-Kt" +readme = "README.md" +requires-python = ">=3.6, <4" +classifiers=[ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "Topic :: Software Development :: Interpreters", + "Topic :: Software Development :: Libraries", + "Topic :: Scientific/Engineering :: Artificial Intelligence", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Prolog", +] +license = {file = "LICENSE"} +keywords = ["prolog", "symbolic ai", "ecosystem", "tuprolog", "2p", "python"] +dependencies = [ + "JPype1~=1.4.1", +] + +[project.urls] +"Homepage" = "https://github.com/tuProlog/2ppy" +"Bug Reports" = "https://github.com/tuProlog/2ppy/issues" +"Source" = "https://github.com/tuProlog/2ppy" diff --git a/requirements.txt b/requirements.txt index f559e34..5e475f8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1 @@ -JPype1==1.3.0 -build>=0.6.0 -twine>=3.4.2 +JPype1==1.4.1 diff --git a/setup.py b/setup.py index e34e8d3..7c0f4bd 100644 --- a/setup.py +++ b/setup.py @@ -1,86 +1,16 @@ - -from setuptools import setup, find_packages -import pathlib -import subprocess - -# current directory -here = pathlib.Path(__file__).parent.resolve() - -version_file = here / 'VERSION' - -print(f"Executing setup.py from {here}") - -# Get the long description from the README file -long_description = (here / 'README.md').read_text(encoding='utf-8') - -def format_git_describe_version(version): - if '-' in version: - splitted = version.split('-') - tag = splitted[0] - index = f"dev{splitted[1]}" #{hex(int(splitted[1]))[2:]}" - # commit = splitted[2] - # return f"{tag}.{index}+{commit}" - return f"{tag}.{index}" - else: - return version - -def get_version_from_git(): - try: - process = subprocess.run(["git", "describe"], cwd=str(here), check=True, capture_output=True) - version = process.stdout.decode('utf-8').strip() - version = format_git_describe_version(version) - with version_file.open('w') as f: - f.write(version) - return version - except subprocess.CalledProcessError: - # with version_file.open('r') as f: - return version_file.read_text().strip() - -# version = os.popen('git describe').read().strip() -version = get_version_from_git() - -print(f"Detected version {version} from git describe") - -# Arguments marked as "Required" below must be included for upload to PyPI. -# Fields marked as "Optional" may be commented out. - -setup( - name='2ppy', # Required - version=version, - description='Python-based implementation of tuProlog -- the open ecosystem for symbolic AI --, based on 2P-Kt', - license='Apache 2.0 License', - long_description=long_description, - long_description_content_type='text/markdown', - url='https://github.com/tuProlog/2ppy', - author='Giovanni Ciatto', - author_email='giovanni.ciatto@unibo.it', - classifiers=[ - 'Development Status :: 3 - Alpha', - 'Intended Audience :: Developers', - 'Topic :: Software Development :: Interpreters', - 'Topic :: Software Development :: Libraries', - 'Topic :: Scientific/Engineering :: Artificial Intelligence', - 'License :: OSI Approved :: Apache Software License', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3 :: Only', - 'Programming Language :: Prolog' - ], - keywords='prolog, symbolic ai, ecosystem, tuprolog, 2p, python', # Optional - # package_dir={'': 'src'}, # Optional - packages=find_packages(), # Required - include_package_data=True, - python_requires='>=3.6, <4', - install_requires=['JPype1==1.3.0'], # Optional - zip_safe = False, - platforms = "Independant", - project_urls={ # Optional - 'Bug Reports': 'https://github.com/tuProlog/2ppy/issues', - # 'Funding': 'https://donate.pypi.org', - # 'Say Thanks!': 'http://saythanks.io/to/example', - 'Source': 'https://github.com/tuProlog/2ppy', - }, -) +from setuptools import setup +from xml.etree import ElementTree + +def java_dependencies() -> list[tuple[str, str, str]]: + namespaces = {'xmlns' : 'http://maven.apache.org/POM/4.0.0'} + tree = ElementTree.parse('pom.xml') + root = tree.getroot() + deps = root.find('xmlns:dependencies', namespaces) + return [ + (dep.find('xmlns:groupId', namespaces).text, + dep.find('xmlns:artifactId', namespaces).text, + dep.find('xmlns:version', namespaces).text) + for dep in deps + ] + +setup() From 7ab50ce853f3efef7ab4d0ed199d9dafdc1e5741 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 29 Mar 2023 17:25:23 +0200 Subject: [PATCH 025/154] Use internal, self contained JRE instead of system JRE --- .github/workflows/ci.yml | 0 .gitignore | 2 +- download-jars.sh | 11 --------- pyproject.toml | 2 +- requirements.txt | 3 ++- setup.py | 47 ++++++++++++++++++++++++++++++++++++++- tuprolog/__init__.py | 8 ++++--- tuprolog/libs/__init__.py | 4 +++- 8 files changed, 58 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100755 download-jars.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e69de29 diff --git a/.gitignore b/.gitignore index a5aa068..a45180d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,9 +6,9 @@ VERSION venv/ .idea/ .vscode/ - *~ *.jar +tuprolog/libs/*/ ### Python ### # Byte-compiled / optimized / DLL files diff --git a/download-jars.sh b/download-jars.sh deleted file mode 100755 index 93da6b7..0000000 --- a/download-jars.sh +++ /dev/null @@ -1,11 +0,0 @@ -get_latest_release() { - curl --silent "https://api.github.com/repos/$1/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/' -} - -TUPROLOG_GITHUB='tuProlog/2p-kt' -TUPROLOG_VERSION=`get_latest_release $TUPROLOG_GITHUB` -TUPROLOG_JAR_URL="https://github.com/$TUPROLOG_GITHUB/releases/download/$TUPROLOG_VERSION/2p-repl-$TUPROLOG_VERSION-redist.jar" - -rm -rf tuprolog/libs/*.jar - -wget -P tuprolog/libs/ $TUPROLOG_JAR_URL || (echo "Failed to download $TUPROLOG_JAR_URL"; echo "Ensure command wget is installed (brew install wget on Mac OS)") diff --git a/pyproject.toml b/pyproject.toml index 4bed5d5..8bf1c1a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools>=61", "wheel", "setuptools-git-versioning<2"] +requires = ["setuptools>=61", "wheel", "setuptools-git-versioning<2", "install-jdk<2"] build-backend = "setuptools.build_meta" [tool.setuptools-git-versioning] diff --git a/requirements.txt b/requirements.txt index 5e475f8..c694340 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ -JPype1==1.4.1 +build==0.10.0 +flake8==6.0.0 diff --git a/setup.py b/setup.py index 7c0f4bd..2888142 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,11 @@ +import os +import jdk +from urllib import request +from pathlib import Path from setuptools import setup from xml.etree import ElementTree +from setuptools.command.build_py import build_py + def java_dependencies() -> list[tuple[str, str, str]]: namespaces = {'xmlns' : 'http://maven.apache.org/POM/4.0.0'} @@ -13,4 +19,43 @@ def java_dependencies() -> list[tuple[str, str, str]]: for dep in deps ] -setup() + +JAR_FOLDER = Path('tuprolog', 'libs') +JAVA_FOLDER = JAR_FOLDER / 'java' + + +def download_jars(): + for group_id, artifact_id, version in java_dependencies(): + jar_name = f'{artifact_id}-{version}.jar' + jar_path = JAR_FOLDER / jar_name + if not jar_path.exists(): + url = f'https://repo1.maven.org/maven2/{group_id.replace(".", "/")}/{artifact_id}/{version}/{jar_name}' + print(f'Downloading {jar_name} from {url}') + response = request.urlopen(url) + data = response.read() + jar_path.write_bytes(data) + else: + print(f'{jar_name} already exists') + + +class BuildPyCommand(build_py): + def run(self): + download_jars() + super().run() + + +def install_java(): + if JAVA_FOLDER.exists(): + print('Java already installed') + return + installation_path = Path(jdk.install('11', jre=True, path=str(JAR_FOLDER))) + installation_path.rename(JAVA_FOLDER) + print(f'Installed Java in {installation_path}') + + +install_java() +setup( + cmdclass={ + 'build_py': BuildPyCommand + } +) diff --git a/tuprolog/__init__.py b/tuprolog/__init__.py index c8de217..a9e494d 100644 --- a/tuprolog/__init__.py +++ b/tuprolog/__init__.py @@ -1,17 +1,19 @@ +import os import logging - # noinspection PyUnresolvedReferences import jpype import jpype.imports -from .libs import CLASSPATH +from .libs import JAVA_HOME, CLASSPATH +os.environ['JAVA_HOME'] = str(JAVA_HOME) logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger('tuprolog') jars = [str(j.resolve()) for j in CLASSPATH.glob('*.jar')] -jpype.startJVM(classpath=jars) +if not jpype.isJVMStarted(): + jpype.startJVM(classpath=jars) # noinspection PyUnresolvedReferences from it.unibo.tuprolog import Info diff --git a/tuprolog/libs/__init__.py b/tuprolog/libs/__init__.py index fcae02a..d5f08e9 100644 --- a/tuprolog/libs/__init__.py +++ b/tuprolog/libs/__init__.py @@ -1,3 +1,5 @@ from pathlib import Path -CLASSPATH = Path(__file__).parents[0] +JAVA_HOME = Path(__file__).parent / 'java' + +CLASSPATH = Path(__file__).parent From 82fc60cd17d6390051443e9252074079ed14697a Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:34:05 +0200 Subject: [PATCH 026/154] Start writing a new ci/cd --- .github/dependabot.yml | 4 +++ .github/workflows/ci.yml | 68 ++++++++++++++++++++++++++++++++++++++++ tuprolog/__init__.py | 1 - 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 56da085..4d905b8 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,3 +9,7 @@ updates: package-ecosystem: maven schedule: interval: daily + - directory: / + package-ecosystem: github-actions + schedule: + interval: weekly diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e69de29..a2cafcc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -0,0 +1,68 @@ +name: CI/CD + +on: + push: + branches: + - "*" + tags: + - "*" + pull_request: + +env: + project-name: 2PPy + +jobs: + build: + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + python-version: [3.6, 3.7, 3.8, 3.9, 3.10, 3.11] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + cache: pip + - name: Install dependencies + run: | + python -m pip install --upgrade pip setuptools wheel + pip install pytest + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + - name: Build + run: | + python -m build --sdist --wheel + - name: Test + run: | + python -m pytest + - name: Upload artifacts + uses: actions/upload-artifact@v2 + with: + name: ${{ env.project-name }}-${{ matrix.python-version }}-${{ matrix.os }} + path: | + dist/*.whl + dist/*.tar.gz + + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install ruff pytest + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + - name: Lint with Flake8 + run: | + # stop the build if there are Python syntax errors or undefined names + python -m flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + python -m flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + + delivery: + runs-on: ubuntu-latest + needs: [build, lint] + steps: + - name: Download Artifacts + run: echo ${{ env.project-name }}-${{ needs.build.strategy.matrix.python-version }}-${{ needs.build.strategy.matrix.os }} diff --git a/tuprolog/__init__.py b/tuprolog/__init__.py index a9e494d..813f411 100644 --- a/tuprolog/__init__.py +++ b/tuprolog/__init__.py @@ -7,7 +7,6 @@ from .libs import JAVA_HOME, CLASSPATH os.environ['JAVA_HOME'] = str(JAVA_HOME) -logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger('tuprolog') jars = [str(j.resolve()) for j in CLASSPATH.glob('*.jar')] From 8a69f9681aa904f87cfac89f400b352245a0a3c6 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 3 Apr 2023 17:52:52 +0200 Subject: [PATCH 027/154] Add ci --- .github/workflows/ci.yml | 10 ++++++++++ setup.py | 42 ++++++++++++++-------------------------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2cafcc..cbca664 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,7 @@ jobs: matrix: os: [ubuntu-latest, windows-latest, macos-latest] python-version: [3.6, 3.7, 3.8, 3.9, 3.10, 3.11] + java-version: [11, 16, 18] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 @@ -25,12 +26,21 @@ jobs: with: python-version: ${{ matrix.python-version }} cache: pip + - name: Set up Maven with Java ${{ matrix.java-version }} + uses: actions/setup-java@v3 + with: + java-version: ${{ matrix.java-version }} + distribution: 'adopt' + architecture: 'x64' + cache: maven - name: Install dependencies run: | python -m pip install --upgrade pip setuptools wheel pip install pytest if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Build + env: + JAVA_VERSION: ${{ matrix.java-version }} run: | python -m build --sdist --wheel - name: Test diff --git a/setup.py b/setup.py index 2888142..48d8048 100644 --- a/setup.py +++ b/setup.py @@ -1,41 +1,27 @@ import os import jdk -from urllib import request +import subprocess from pathlib import Path from setuptools import setup -from xml.etree import ElementTree from setuptools.command.build_py import build_py -def java_dependencies() -> list[tuple[str, str, str]]: - namespaces = {'xmlns' : 'http://maven.apache.org/POM/4.0.0'} - tree = ElementTree.parse('pom.xml') - root = tree.getroot() - deps = root.find('xmlns:dependencies', namespaces) - return [ - (dep.find('xmlns:groupId', namespaces).text, - dep.find('xmlns:artifactId', namespaces).text, - dep.find('xmlns:version', namespaces).text) - for dep in deps - ] - - JAR_FOLDER = Path('tuprolog', 'libs') JAVA_FOLDER = JAR_FOLDER / 'java' def download_jars(): - for group_id, artifact_id, version in java_dependencies(): - jar_name = f'{artifact_id}-{version}.jar' - jar_path = JAR_FOLDER / jar_name - if not jar_path.exists(): - url = f'https://repo1.maven.org/maven2/{group_id.replace(".", "/")}/{artifact_id}/{version}/{jar_name}' - print(f'Downloading {jar_name} from {url}') - response = request.urlopen(url) - data = response.read() - jar_path.write_bytes(data) - else: - print(f'{jar_name} already exists') + proc = subprocess.Popen(['mvn.cmd' , '-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + stdout, stderr = proc.communicate() + if proc.returncode != 0: + raise RuntimeError(f'Could not run mvn.cmd: {stderr}') + if 'Apache Maven' not in stdout: + raise RuntimeError(f'Could not find Apache Maven in {stdout}') + print('Downloading JARs...') + proc = subprocess.Popen(['mvn.cmd', 'dependency:copy-dependencies', f'-DoutputDirectory="{JAR_FOLDER}"'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + stdout, stderr = proc.communicate() + if proc.returncode != 0: + raise RuntimeError(f'Error while downloading JARs: {stdout} {stderr}') class BuildPyCommand(build_py): @@ -48,7 +34,9 @@ def install_java(): if JAVA_FOLDER.exists(): print('Java already installed') return - installation_path = Path(jdk.install('11', jre=True, path=str(JAR_FOLDER))) + java_version = os.getenv('JAVA_VERSION', '11') + print(f'Installing Java {java_version}...') + installation_path = Path(jdk.install(java_version), jre=True, path=str(JAR_FOLDER)) installation_path.rename(JAVA_FOLDER) print(f'Installed Java in {installation_path}') From 29e0de309b1ae7ef00522a337c23f7223ca458ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:53:20 +0000 Subject: [PATCH 028/154] Bump actions/upload-artifact from 2 to 3 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- .github/workflows/deploy.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cbca664..87fc55f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: run: | python -m pytest - name: Upload artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: ${{ env.project-name }}-${{ matrix.python-version }}-${{ matrix.os }} path: | diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ad7c410..df9e395 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -45,7 +45,7 @@ jobs: - name: Archive Dist Artifacts if: failure() || success() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: dist path: './dist' From 0735335fea4739562e9f98aa8843c3d717d98897 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 3 Apr 2023 17:54:42 +0200 Subject: [PATCH 029/154] Support only python 3.9 to 3.11 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cbca664..052dbf0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python-version: [3.6, 3.7, 3.8, 3.9, 3.10, 3.11] + python-version: [3.9, 3.10, 3.11] java-version: [11, 16, 18] runs-on: ${{ matrix.os }} steps: From 1051c22c023a3b72d288c0ff766aca0ab782a893 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 3 Apr 2023 17:56:25 +0200 Subject: [PATCH 030/154] Fix versions --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 052dbf0..f63f08b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,8 +16,8 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python-version: [3.9, 3.10, 3.11] - java-version: [11, 16, 18] + python-version: ['3.9', '3.10', '3.11'] + java-version: ['11', '16', '18'] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 From d134ea68457f080a781bcd9c1d919d667a9ee545 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 3 Apr 2023 17:58:53 +0200 Subject: [PATCH 031/154] Fix setup --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 48d8048..0b7a599 100644 --- a/setup.py +++ b/setup.py @@ -37,7 +37,7 @@ def install_java(): java_version = os.getenv('JAVA_VERSION', '11') print(f'Installing Java {java_version}...') installation_path = Path(jdk.install(java_version), jre=True, path=str(JAR_FOLDER)) - installation_path.rename(JAVA_FOLDER) + installation_path = installation_path.rename(JAVA_FOLDER) print(f'Installed Java in {installation_path}') From a62ca3e5ae60b64ccfb64fb417c8fb480f38ecde Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 3 Apr 2023 17:59:16 +0200 Subject: [PATCH 032/154] Disable fail fast in ci --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f63f08b..dd62eaa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,7 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] python-version: ['3.9', '3.10', '3.11'] java-version: ['11', '16', '18'] + fail-fast: false runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 From 82194f7db11af9fc6bb00ef40576b2630056994d Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 3 Apr 2023 18:04:24 +0200 Subject: [PATCH 033/154] Fix maven executable name --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 0b7a599..2e7f127 100644 --- a/setup.py +++ b/setup.py @@ -8,17 +8,17 @@ JAR_FOLDER = Path('tuprolog', 'libs') JAVA_FOLDER = JAR_FOLDER / 'java' - +MAVEN_EXECUTABLE = ['mvn', '--batch-mode'] def download_jars(): - proc = subprocess.Popen(['mvn.cmd' , '-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + proc = subprocess.Popen(MAVEN_EXECUTABLE + ['-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) stdout, stderr = proc.communicate() if proc.returncode != 0: raise RuntimeError(f'Could not run mvn.cmd: {stderr}') if 'Apache Maven' not in stdout: raise RuntimeError(f'Could not find Apache Maven in {stdout}') print('Downloading JARs...') - proc = subprocess.Popen(['mvn.cmd', 'dependency:copy-dependencies', f'-DoutputDirectory="{JAR_FOLDER}"'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + proc = subprocess.Popen(MAVEN_EXECUTABLE + ['dependency:copy-dependencies', f'-DoutputDirectory="{JAR_FOLDER}"'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) stdout, stderr = proc.communicate() if proc.returncode != 0: raise RuntimeError(f'Error while downloading JARs: {stdout} {stderr}') From 55028e961d094d6a67fb977c53287aeec92b3b64 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 3 Apr 2023 18:06:59 +0200 Subject: [PATCH 034/154] Fix static parse errors --- tuprolog/core/parsing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tuprolog/core/parsing.py b/tuprolog/core/parsing.py index 3ebf426..1974cf1 100644 --- a/tuprolog/core/parsing.py +++ b/tuprolog/core/parsing.py @@ -4,7 +4,7 @@ # noinspection PyUnresolvedReferences import it.unibo.tuprolog.core.parsing as _parsing from tuprolog.core import Term, Struct, Constant, Var, Atom, Numeric, Integer, Real, Clause -from tuprolog.jvmutils import InputStream +from tuprolog.jvmutils import InputStream, ensure_input_steam TermParser = _parsing.TermParser From 722c2778fdde9d150affab6cc210e1a7abd02672 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 16:07:53 +0000 Subject: [PATCH 035/154] Bump actions/checkout from 2 to 3 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/deploy.yml | 2 +- .github/workflows/quick-check.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ad7c410..d9fe060 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -21,7 +21,7 @@ jobs: javac --version - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 # all history diff --git a/.github/workflows/quick-check.yml b/.github/workflows/quick-check.yml index b538daf..3589ec7 100644 --- a/.github/workflows/quick-check.yml +++ b/.github/workflows/quick-check.yml @@ -22,7 +22,7 @@ jobs: javac --version - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 # all history From 09db25845e5f207891d8d4c10fc8f6adea8a9123 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:33:45 +0200 Subject: [PATCH 036/154] Patch maven broken resolution, update library and fix tests --- setup.py | 31 +++++++- test/core/test_formatters.py | 7 +- test/core/test_visitors.py | 21 +++-- tuprolog/core/formatters.py | 111 +-------------------------- tuprolog/core/parsing.py | 8 +- tuprolog/core/visitors.py | 103 ++----------------------- tuprolog/solve/classic/__init__.py | 6 +- tuprolog/solve/library/__init__.py | 45 +++++------ tuprolog/solve/sideffcts/__init__.py | 8 +- tuprolog/theory/__init__.py | 5 +- 10 files changed, 89 insertions(+), 256 deletions(-) diff --git a/setup.py b/setup.py index 2e7f127..462d138 100644 --- a/setup.py +++ b/setup.py @@ -10,6 +10,31 @@ JAVA_FOLDER = JAR_FOLDER / 'java' MAVEN_EXECUTABLE = ['mvn', '--batch-mode'] + +def fallback_download_jars(): + print('Downloading JARs from GitHub...') + def java_dependencies() -> list[tuple[str, str, str]]: + from xml.etree import ElementTree + namespaces = {'xmlns' : 'http://maven.apache.org/POM/4.0.0'} + tree = ElementTree.parse('pom.xml') + root = tree.getroot() + deps = root.find('xmlns:dependencies', namespaces) + return [ + (dep.find('xmlns:groupId', namespaces).text, + dep.find('xmlns:artifactId', namespaces).text, + dep.find('xmlns:version', namespaces).text) + for dep in deps + ] + from urllib.parse import quote + _, _, version = java_dependencies()[0] + all_in_one_jar = f'https://github.com/tuProlog/2p-kt/releases/download/{quote(version)}/2p-{version}-full.jar' + print(f'Downloading {all_in_one_jar}') + proc = subprocess.Popen(['curl', '--silent', '-L', all_in_one_jar, '--output', str(JAR_FOLDER / f'2p-{version}-full.jar')], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + stdout, stderr = proc.communicate() + if proc.returncode != 0: + raise RuntimeError(f'Error while downloading JARs from GitHub: {stdout} {stderr}') + + def download_jars(): proc = subprocess.Popen(MAVEN_EXECUTABLE + ['-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) stdout, stderr = proc.communicate() @@ -26,7 +51,11 @@ def download_jars(): class BuildPyCommand(build_py): def run(self): - download_jars() + try: + download_jars() + except: + print('Could not download JARs using Maven, falling back to GitHub') + fallback_download_jars() super().run() diff --git a/test/core/test_formatters.py b/test/core/test_formatters.py index c9a03ff..25dea01 100644 --- a/test/core/test_formatters.py +++ b/test/core/test_formatters.py @@ -1,15 +1,12 @@ import unittest from tuprolog.core import * -from tuprolog.core.formatters import AbstractTermFormatter +from tuprolog.core.formatters import DefaultTermFormatter class TestFormatters(unittest.TestCase): def test_term_formatter(self): - class MyFormatter(AbstractTermFormatter): - def defaultValue(self, term): - return str(term) - formatter = MyFormatter() + formatter = DefaultTermFormatter() for term in [Atom.of('a'), Integer.of(1), Var.of("X")]: self.assertEqual(formatter.format(term), str(term)) diff --git a/test/core/test_visitors.py b/test/core/test_visitors.py index 4fad903..0890237 100644 --- a/test/core/test_visitors.py +++ b/test/core/test_visitors.py @@ -1,19 +1,26 @@ import unittest from tuprolog.core import * -from tuprolog.core.visitors import AbstractTermVisitor +from tuprolog.core.visitors import DefaultTermVisitor +import jpype.imports +import kotlin.jvm.functions as _functions + +@jpype.JImplements(_functions.Function1) +class Lambda: + def __init__(self, f): + self.f = f + + @jpype.JOverride + def invoke(self, arg): + return self.f(arg) class TestVisitors(unittest.TestCase): def test_term_visitor(self): - class MyVisitor(AbstractTermVisitor): - def defaultValue(self, term): - return 'a' - visitor = MyVisitor() - someTerm = Atom.of('b') + visitor = DefaultTermVisitor.of(Lambda(lambda term: 'a')) for term in [Atom.of('a'), Integer.of(1), Var.of("X")]: self.assertEqual(term.accept(visitor), 'a') if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() diff --git a/tuprolog/core/formatters.py b/tuprolog/core/formatters.py index 730cad0..52de53d 100644 --- a/tuprolog/core/formatters.py +++ b/tuprolog/core/formatters.py @@ -2,114 +2,9 @@ # noinspection PyUnresolvedReferences import jpype import jpype.imports -from tuprolog.core import Formatter, TermFormatter -from tuprolog.core.visitors import AbstractTermVisitor - - -@jpype.JImplements(Formatter) -class AbstractFormatter(object): - @jpype.JOverride - def format(self, term): - raise NotImplementedError() - - -@jpype.JImplements(TermFormatter) -class AbstractTermFormatter(AbstractFormatter, AbstractTermVisitor): - @jpype.JOverride - def format(self, term): - return term.accept(self) - - @jpype.JOverride - def defaultValue(self, term): - return super(AbstractTermVisitor).defaultValue(self, term) - - @jpype.JOverride - def visitTerm(self, term): - return super(AbstractTermVisitor, self).visitTerm(term) - - @jpype.JOverride - def visitVar(self, term): - return super(AbstractTermVisitor, self).visitVar(term) - - @jpype.JOverride - def visitConstant(self, term): - return super(AbstractTermVisitor, self).visitConstant(term) - - @jpype.JOverride - def visitStruct(self, term): - return super(AbstractTermVisitor, self).visitStruct(term) - - @jpype.JOverride - def visitCollection(self, term): - return super(AbstractTermVisitor, self).visitCollection(term) - - @jpype.JOverride - def visitAtom(self, term): - return super(AbstractTermVisitor, self).visitAtom(term) - - @jpype.JOverride - def visitTruth(self, term): - return super(AbstractTermVisitor, self).visitTruth(term) - - @jpype.JOverride - def visitNumeric(self, term): - return super(AbstractTermVisitor, self).visitNumeric(term) - - @jpype.JOverride - def visitInteger(self, term): - return super(AbstractTermVisitor, self).visitInteger(term) - - @jpype.JOverride - def visitReal(self, term): - return super(AbstractTermVisitor, self).visitReal(term) - - @jpype.JOverride - def visitBlock(self, term): - return super(AbstractTermVisitor, self).visitBlock(term) - - @jpype.JOverride - def visitEmpty(self, term): - return super(AbstractTermVisitor, self).visitEmpty(term) - - @jpype.JOverride - def visitEmptyBlock(self, term): - return super(AbstractTermVisitor, self).visitEmptyBlock(term) - - @jpype.JOverride - def visitList(self, term): - return super(AbstractTermVisitor, self).visitList(term) - - @jpype.JOverride - def visitCons(self, term): - return super(AbstractTermVisitor, self).visitCons(term) - - @jpype.JOverride - def visitEmptyList(self, term): - return super(AbstractTermVisitor, self).visitEmptyList(term) - - @jpype.JOverride - def visitTuple(self, term): - return super(AbstractTermVisitor, self).visitTuple(term) - - @jpype.JOverride - def visitIndicator(self, term): - return super(AbstractTermVisitor, self).visitIndicator(term) - - @jpype.JOverride - def visitClause(self, term): - return super(AbstractTermVisitor, self).visitClause(term) - - @jpype.JOverride - def visitRule(self, term): - return super(AbstractTermVisitor, self).visitRule(term) - - @jpype.JOverride - def visitFact(self, term): - return super(AbstractTermVisitor, self).visitFact(term) - - @jpype.JOverride - def visitDirective(self, term): - return super(AbstractTermVisitor, self).visitDirective(term) +from tuprolog.core import TermFormatter +import it.unibo.tuprolog.core.impl as _impl +DefaultTermFormatter = _impl.SimpleTermFormatter logger.debug("Loaded compatibility layer for JVM subtypes of " + str(TermFormatter.class_.getName())) diff --git a/tuprolog/core/parsing.py b/tuprolog/core/parsing.py index 1974cf1..5f88dad 100644 --- a/tuprolog/core/parsing.py +++ b/tuprolog/core/parsing.py @@ -23,9 +23,9 @@ def term_parser(with_default_operators: bool=True, operators: OperatorSet=None) -> TermParser: if operators is None: if with_default_operators: - return TermParser.getWithDefaultOperators() + return TermParser.withDefaultOperators() else: - return TermParser.getWithNoOperator() + return TermParser.withNoOperator() else: if with_default_operators: return TermParser.withOperators(DEFAULT_OPERATORS.plus(operators)) @@ -36,9 +36,9 @@ def term_parser(with_default_operators: bool=True, operators: OperatorSet=None) def term_reader(with_default_operators: bool=True, operators: OperatorSet=None) -> TermParser: if operators is None: if with_default_operators: - return TermReader.getWithDefaultOperators() + return TermReader.withDefaultOperators() else: - return TermReader.getWithNoOperator() + return TermReader.withNoOperator() else: if with_default_operators: return TermReader.withOperators(DEFAULT_OPERATORS.plus(operators)) diff --git a/tuprolog/core/visitors.py b/tuprolog/core/visitors.py index ca0f246..bec3593 100644 --- a/tuprolog/core/visitors.py +++ b/tuprolog/core/visitors.py @@ -1,102 +1,9 @@ from tuprolog import logger import jpype -from tuprolog.core import TermVisitor +# noinspection PyUnresolvedReferences +import jpype.imports +import it.unibo.tuprolog.core.visitors as _visitors +DefaultTermVisitor = _visitors.DefaultTermVisitor -@jpype.JImplements(TermVisitor) -class AbstractTermVisitor(object): - - @jpype.JOverride - def defaultValue(self, term): - raise NotImplementedError() - - @jpype.JOverride - def visitTerm(self, term): - return TermVisitor.DefaultImpls.visitTerm(self, term) - - @jpype.JOverride - def visitVar(self, term): - return TermVisitor.DefaultImpls.visitVar(self, term) - - @jpype.JOverride - def visitConstant(self, term): - return TermVisitor.DefaultImpls.visitConstant(self, term) - - @jpype.JOverride - def visitStruct(self, term): - return TermVisitor.DefaultImpls.visitStruct(self, term) - - @jpype.JOverride - def visitCollection(self, term): - return TermVisitor.DefaultImpls.visitCollection(self, term) - - @jpype.JOverride - def visitAtom(self, term): - return TermVisitor.DefaultImpls.visitAtom(self, term) - - @jpype.JOverride - def visitTruth(self, term): - return TermVisitor.DefaultImpls.visitTruth(self, term) - - @jpype.JOverride - def visitNumeric(self, term): - return TermVisitor.DefaultImpls.visitNumeric(self, term) - - @jpype.JOverride - def visitInteger(self, term): - return TermVisitor.DefaultImpls.visitInteger(self, term) - - @jpype.JOverride - def visitReal(self, term): - return TermVisitor.DefaultImpls.visitReal(self, term) - - @jpype.JOverride - def visitBlock(self, term): - return TermVisitor.DefaultImpls.visitBlock(self, term) - - @jpype.JOverride - def visitEmpty(self, term): - return TermVisitor.DefaultImpls.visitEmpty(self, term) - - @jpype.JOverride - def visitEmptyBlock(self, term): - return TermVisitor.DefaultImpls.visitEmptyBlock(self, term) - - @jpype.JOverride - def visitList(self, term): - return TermVisitor.DefaultImpls.visitList(self, term) - - @jpype.JOverride - def visitCons(self, term): - return TermVisitor.DefaultImpls.visitCons(self, term) - - @jpype.JOverride - def visitEmptyList(self, term): - return TermVisitor.DefaultImpls.visitEmptyList(self, term) - - @jpype.JOverride - def visitTuple(self, term): - return TermVisitor.DefaultImpls.visitTuple(self, term) - - @jpype.JOverride - def visitIndicator(self, term): - return TermVisitor.DefaultImpls.visitIndicator(self, term) - - @jpype.JOverride - def visitClause(self, term): - return TermVisitor.DefaultImpls.visitClause(self, term) - - @jpype.JOverride - def visitRule(self, term): - return TermVisitor.DefaultImpls.visitRule(self, term) - - @jpype.JOverride - def visitFact(self, term): - return TermVisitor.DefaultImpls.visitFact(self, term) - - @jpype.JOverride - def visitDirective(self, term): - return TermVisitor.DefaultImpls.visitDirective(self, term) - - -logger.debug("Loaded compatibility layer for JVM subtypes of " + str(TermVisitor.class_.getName())) +logger.debug("Loaded compatibility layer for JVM subtypes of " + str(DefaultTermVisitor.class_.getName())) diff --git a/tuprolog/solve/classic/__init__.py b/tuprolog/solve/classic/__init__.py index c2de785..f02d278 100644 --- a/tuprolog/solve/classic/__init__.py +++ b/tuprolog/solve/classic/__init__.py @@ -1,15 +1,15 @@ from tuprolog.solve.flags import DEFAULT_FLAG_STORE, FlagStore -from tuprolog.solve.library import libraries, Libraries +from tuprolog.solve.library import libraries, Library from tuprolog.solve.channel import InputChannel, OutputChannel, std_out, std_in, std_err, warn from tuprolog.theory import theory, mutable_theory, Theory from tuprolog.solve import Solver, SolverFactory -_CLASSIC_SOLVER_FACTORY = Solver.getClassic() +_CLASSIC_SOLVER_FACTORY = Solver.prolog() def classic_solver( - libraries: Libraries = libraries(), + libraries: Library = libraries(), flags: FlagStore = DEFAULT_FLAG_STORE, static_kb: Theory = theory(), dynamic_kb: Theory = mutable_theory(), diff --git a/tuprolog/solve/library/__init__.py b/tuprolog/solve/library/__init__.py index 9829fe3..eb09cd7 100644 --- a/tuprolog/solve/library/__init__.py +++ b/tuprolog/solve/library/__init__.py @@ -15,49 +15,44 @@ Library = _library.Library -Libraries = _library.Libraries - -LibraryGroup = _library.LibraryGroup - -AliasedLibrary = _library.AliasedLibrary +Pluggable = _library.Pluggable def library( - alias: str = None, - primitives: Mapping[Signature, Primitive] = dict(), - theory: Theory = theory(), - operators: OperatorSet = operator_set(), - functions: Mapping[Signature, LogicFunction] = dict(), -) -> Union[Library, AliasedLibrary]: + alias: str = None, + primitives: Mapping[Signature, Primitive] = dict(), + theory: Theory = theory(), + operators: OperatorSet = operator_set(), + functions: Mapping[Signature, LogicFunction] = dict(), +) -> Union[Library, Pluggable]: if alias is None: - return Library.unaliased(primitives, theory, operators, functions) + return Library.of(primitives, theory.clauses, operators, functions) else: - return Library.aliased(alias, primitives, theory, operators, functions) + return Library.of(alias, primitives, theory.clauses, operators, functions) -def aliased(alias: str, library: Library) -> AliasedLibrary: +def aliased(alias: str, library: Library) -> Library: return Library.of(alias, library) def libraries( - *libs: Union[Libraries, AliasedLibrary, Iterable[Union[Libraries, AliasedLibrary]]], + *libs: Union[Library, Iterable[Library]], **kwargs: Library -) -> Libraries: +) -> Library: all_libraries = [] - aliased_libs = [] queue = list(libs) while len(queue) > 0: current = queue.pop() - if isinstance(current, Libraries): + if isinstance(current, Library): all_libraries.append(current) - elif isinstance(current, AliasedLibrary): - aliased_libs.append(current) - else: + elif isinstance(current, Iterable): queue.extend(current) - for alias in kwargs: - aliased_libs.append(aliased(alias, kwargs[alias])) - first = Libraries.of(jiterable(aliased_libs)) - return reduce(lambda a, b: a.plus(b), all_libraries, first) + else: + raise TypeError(f'Expected Library or Iterable[Library], got {type(current)}') + for alias, library in kwargs.items(): + if isinstance(library, Library): + all_libraries.append(aliased(alias, kwargs[alias])) + return reduce(lambda a, b: a.plus(b), all_libraries, Library.of({}, [], operator_set(), {})) logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.library.*") \ No newline at end of file diff --git a/tuprolog/solve/sideffcts/__init__.py b/tuprolog/solve/sideffcts/__init__.py index 5fa38f3..5314060 100644 --- a/tuprolog/solve/sideffcts/__init__.py +++ b/tuprolog/solve/sideffcts/__init__.py @@ -19,7 +19,7 @@ # noinspection PyUnresolvedReferences from tuprolog.core.operators import Operator, OperatorSet # noinspection PyUnresolvedReferences -from tuprolog.solve.library import Library, AliasedLibrary, Libraries, libraries as new_libraries +from tuprolog.solve.library import Library, libraries as new_libraries # noinspection PyUnresolvedReferences from tuprolog.solve.channel import InputChannel, OutputChannel from tuprolog.pyutils import iterable_or_varargs, dict_or_keyword_args @@ -84,12 +84,12 @@ def update_library(alias: str, library: Library) -> SideEffect.UpdateLibrary: return SideEffect.UpdateLibrary(alias, library) -def add_libraries(*libraries: Union[Libraries, AliasedLibrary]) -> SideEffect.AddLibraries: +def add_libraries(*libraries: Library) -> SideEffect.AddLibraries: return SideEffect.AddLibraries(new_libraries(libraries)) -def reset_libraries(*libraries: Union[Libraries, AliasedLibrary]) -> SideEffect.ResetLibraries: - return SideEffect.ResetLibraries(new_libraries(libraries)) +def reset_libraries(*libraries: Library) -> SideEffect.ResetRuntime: + return SideEffect.ResetRuntime(new_libraries(libraries)) def set_operators(*operators: Union[Operator, Iterable[Operator]]) -> SideEffect.SetOperators: diff --git a/tuprolog/theory/__init__.py b/tuprolog/theory/__init__.py index 19e1ac0..11ab38e 100644 --- a/tuprolog/theory/__init__.py +++ b/tuprolog/theory/__init__.py @@ -3,6 +3,7 @@ import jpype.imports # noinspection PyUnresolvedReferences import it.unibo.tuprolog.theory as _theory +import it.unibo.tuprolog.unify as _unify from typing import Iterable, Union from tuprolog.core import Clause from tuprolog.pyutils import iterable_or_varargs @@ -14,13 +15,15 @@ RetractResult = _theory.RetractResult +Unificator = _unify.Unificator + def theory(*clauses: Union[Clause, Iterable[Clause]]) -> Theory: return iterable_or_varargs(clauses, lambda ts: Theory.of(jiterable(ts))) def mutable_theory(*clauses: Union[Clause, Iterable[Clause]]) -> MutableTheory: - return iterable_or_varargs(clauses, lambda ts: MutableTheory.of(jiterable(ts))) + return iterable_or_varargs(clauses, lambda ts: MutableTheory.of(Unificator.getDefault(), jiterable(ts))) logger.debug("Loaded JVM classes from it.unibo.tuprolog.theory.*") From 6e4e88b55034428f32909e0eedc6bdd7005bc19a Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:39:43 +0200 Subject: [PATCH 037/154] Install wheels in ci before tests --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9e82faf..b6ee9c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,6 +44,9 @@ jobs: JAVA_VERSION: ${{ matrix.java-version }} run: | python -m build --sdist --wheel + - name: Install + run: | + pip install dist/*.whl - name: Test run: | python -m pytest From 07fe7970e41e6df782f5fcf68d3d9fb410a6d344 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:45:16 +0200 Subject: [PATCH 038/154] Fix artifacts name collision --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b6ee9c9..1f0947c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,7 +53,7 @@ jobs: - name: Upload artifacts uses: actions/upload-artifact@v3 with: - name: ${{ env.project-name }}-${{ matrix.python-version }}-${{ matrix.os }} + name: ${{ env.project-name }}-${{ matrix.python-version }}-${{ matrix.os }}-java${{ matrix.java-version }} path: | dist/*.whl dist/*.tar.gz From 7130c77d05e27a1e0645b3b5aebb090201c8e64f Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:47:38 +0200 Subject: [PATCH 039/154] Fix ci default shell --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f0947c..27890c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,10 @@ on: env: project-name: 2PPy +defaults: + run: + shell: bash + jobs: build: strategy: From 5c9e9b080a5ce5ab87d83948aba8aa7702d1ae5a Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:52:20 +0200 Subject: [PATCH 040/154] Fix setup on windows --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 462d138..ce9faee 100644 --- a/setup.py +++ b/setup.py @@ -66,7 +66,7 @@ def install_java(): java_version = os.getenv('JAVA_VERSION', '11') print(f'Installing Java {java_version}...') installation_path = Path(jdk.install(java_version), jre=True, path=str(JAR_FOLDER)) - installation_path = installation_path.rename(JAVA_FOLDER) + installation_path = installation_path.rename(JAVA_FOLDER.resolve()) print(f'Installed Java in {installation_path}') From c1b7beca5a76384210f9d940ede632d33841f116 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:59:42 +0200 Subject: [PATCH 041/154] Fix attempt for ci windows --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index ce9faee..6755593 100644 --- a/setup.py +++ b/setup.py @@ -65,8 +65,8 @@ def install_java(): return java_version = os.getenv('JAVA_VERSION', '11') print(f'Installing Java {java_version}...') - installation_path = Path(jdk.install(java_version), jre=True, path=str(JAR_FOLDER)) - installation_path = installation_path.rename(JAVA_FOLDER.resolve()) + installation_path = Path(jdk.install(java_version), jre=True, path=str(JAR_FOLDER.resolve())) + installation_path = installation_path.rename(JAVA_FOLDER) print(f'Installed Java in {installation_path}') From fe9221b0432e24e5dd119baabe141a78b5b0c805 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 12:06:19 +0200 Subject: [PATCH 042/154] Use absolute paths in setup --- setup.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 6755593..e5f836d 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ from setuptools.command.build_py import build_py -JAR_FOLDER = Path('tuprolog', 'libs') +JAR_FOLDER = Path(__file__).parent / 'tuprolog' / 'libs' JAVA_FOLDER = JAR_FOLDER / 'java' MAVEN_EXECUTABLE = ['mvn', '--batch-mode'] @@ -64,9 +64,12 @@ def install_java(): print('Java already installed') return java_version = os.getenv('JAVA_VERSION', '11') - print(f'Installing Java {java_version}...') - installation_path = Path(jdk.install(java_version), jre=True, path=str(JAR_FOLDER.resolve())) - installation_path = installation_path.rename(JAVA_FOLDER) + destination_folder = str(JAR_FOLDER.resolve()) + print(f'Downloading Java {java_version} in {destination_folder}...') + installation_path = Path(jdk.install(java_version), jre=True, path=destination_folder) + destination_folder = str(JAVA_FOLDER.resolve()) + print(f'Installing Java {java_version} in {destination_folder}...') + installation_path = installation_path.rename(destination_folder) print(f'Installed Java in {installation_path}') From 84c2affb5f890e9ee2ffb37be87adf0db2064c8d Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 12:13:15 +0200 Subject: [PATCH 043/154] Revert and fix setup --- setup.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index e5f836d..e8a6791 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ from setuptools.command.build_py import build_py -JAR_FOLDER = Path(__file__).parent / 'tuprolog' / 'libs' +JAR_FOLDER = Path('tuprolog', 'libs') JAVA_FOLDER = JAR_FOLDER / 'java' MAVEN_EXECUTABLE = ['mvn', '--batch-mode'] @@ -66,9 +66,9 @@ def install_java(): java_version = os.getenv('JAVA_VERSION', '11') destination_folder = str(JAR_FOLDER.resolve()) print(f'Downloading Java {java_version} in {destination_folder}...') - installation_path = Path(jdk.install(java_version), jre=True, path=destination_folder) - destination_folder = str(JAVA_FOLDER.resolve()) - print(f'Installing Java {java_version} in {destination_folder}...') + installation_path = Path(jdk.install(java_version, jre=True, path=destination_folder)) + destination_folder = JAVA_FOLDER + print(f'Installing Java in {destination_folder}...') installation_path = installation_path.rename(destination_folder) print(f'Installed Java in {installation_path}') From bdb7507b3bc5eb1e57a95b6d33a27493d33f794c Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 12:32:54 +0200 Subject: [PATCH 044/154] Fix missing jre for java 16 --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index e8a6791..20fb27d 100644 --- a/setup.py +++ b/setup.py @@ -64,9 +64,9 @@ def install_java(): print('Java already installed') return java_version = os.getenv('JAVA_VERSION', '11') - destination_folder = str(JAR_FOLDER.resolve()) + destination_folder = str(JAR_FOLDER) print(f'Downloading Java {java_version} in {destination_folder}...') - installation_path = Path(jdk.install(java_version, jre=True, path=destination_folder)) + installation_path = Path(jdk.install(java_version, jre=not java_version.startswith('16'), path=destination_folder)) destination_folder = JAVA_FOLDER print(f'Installing Java in {destination_folder}...') installation_path = installation_path.rename(destination_folder) From ddc14a1313ce098782f7d9c245be1461d4ef528d Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 13:17:24 +0200 Subject: [PATCH 045/154] Update ci --- .github/workflows/ci.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 27890c7..1291a0b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,11 +19,11 @@ jobs: build: strategy: matrix: - os: [ubuntu-latest, windows-latest, macos-latest] + os: [ubuntu, windows, macos] python-version: ['3.9', '3.10', '3.11'] java-version: ['11', '16', '18'] fail-fast: false - runs-on: ${{ matrix.os }} + runs-on: ${{ matrix.os }}-latest steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} @@ -83,4 +83,9 @@ jobs: needs: [build, lint] steps: - name: Download Artifacts - run: echo ${{ env.project-name }}-${{ needs.build.strategy.matrix.python-version }}-${{ needs.build.strategy.matrix.os }} + uses: actions/download-artifact@v3 + with: + path: ${{ env.project-name }}-3.11-ubuntu-java18 + - name: List files + run: | + ls -lah From 4aa7fe19ed8ad20c0b73376ae748f8d4f84cebbc Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 13:37:18 +0200 Subject: [PATCH 046/154] Update pyproject.toml --- pyproject.toml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8bf1c1a..55a9678 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ authors = [ ] description = "Python-based implementation of tuProlog -- the open ecosystem for symbolic AI --, based on 2P-Kt" readme = "README.md" -requires-python = ">=3.6, <4" +requires-python = ">=3.9, <4" classifiers=[ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", @@ -39,5 +39,4 @@ dependencies = [ [project.urls] "Homepage" = "https://github.com/tuProlog/2ppy" -"Bug Reports" = "https://github.com/tuProlog/2ppy/issues" -"Source" = "https://github.com/tuProlog/2ppy" +"Bug" = "https://github.com/tuProlog/2ppy/issues" From e02d14dcc7e77b3ca460121a58b720574f628ab3 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 20:09:32 +0200 Subject: [PATCH 047/154] Drop fallback and patch maven installation --- .github/workflows/ci.yml | 2 +- pom.xml | 11 +++++++++++ setup.py | 35 ++++------------------------------- 3 files changed, 16 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1291a0b..0b084d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,7 +85,7 @@ jobs: - name: Download Artifacts uses: actions/download-artifact@v3 with: - path: ${{ env.project-name }}-3.11-ubuntu-java18 + name: ${{ env.project-name }}-3.11-ubuntu-java18 - name: List files run: | ls -lah diff --git a/pom.xml b/pom.xml index 78268ce..c208e05 100644 --- a/pom.xml +++ b/pom.xml @@ -4,11 +4,22 @@ com.mycompany.app my-app 1 + + org.jetbrains.kotlin + kotlin-bom + 1.8.10 + it.unibo.tuprolog repl-jvm 0.31.1-dev02+0cd8a1ae6 + + + org.jetbrains.kotlin + kotlin-bom + + diff --git a/setup.py b/setup.py index 20fb27d..e857ff3 100644 --- a/setup.py +++ b/setup.py @@ -11,39 +11,16 @@ MAVEN_EXECUTABLE = ['mvn', '--batch-mode'] -def fallback_download_jars(): - print('Downloading JARs from GitHub...') - def java_dependencies() -> list[tuple[str, str, str]]: - from xml.etree import ElementTree - namespaces = {'xmlns' : 'http://maven.apache.org/POM/4.0.0'} - tree = ElementTree.parse('pom.xml') - root = tree.getroot() - deps = root.find('xmlns:dependencies', namespaces) - return [ - (dep.find('xmlns:groupId', namespaces).text, - dep.find('xmlns:artifactId', namespaces).text, - dep.find('xmlns:version', namespaces).text) - for dep in deps - ] - from urllib.parse import quote - _, _, version = java_dependencies()[0] - all_in_one_jar = f'https://github.com/tuProlog/2p-kt/releases/download/{quote(version)}/2p-{version}-full.jar' - print(f'Downloading {all_in_one_jar}') - proc = subprocess.Popen(['curl', '--silent', '-L', all_in_one_jar, '--output', str(JAR_FOLDER / f'2p-{version}-full.jar')], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) - stdout, stderr = proc.communicate() - if proc.returncode != 0: - raise RuntimeError(f'Error while downloading JARs from GitHub: {stdout} {stderr}') - - def download_jars(): - proc = subprocess.Popen(MAVEN_EXECUTABLE + ['-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + print('Checking Maven...') + proc = subprocess.Popen(MAVEN_EXECUTABLE + ['-version'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) stdout, stderr = proc.communicate() if proc.returncode != 0: raise RuntimeError(f'Could not run mvn.cmd: {stderr}') if 'Apache Maven' not in stdout: raise RuntimeError(f'Could not find Apache Maven in {stdout}') print('Downloading JARs...') - proc = subprocess.Popen(MAVEN_EXECUTABLE + ['dependency:copy-dependencies', f'-DoutputDirectory="{JAR_FOLDER}"'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + proc = subprocess.Popen(MAVEN_EXECUTABLE + ['dependency:copy-dependencies', f'-DoutputDirectory={JAR_FOLDER}'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd=Path(__file__).parent) stdout, stderr = proc.communicate() if proc.returncode != 0: raise RuntimeError(f'Error while downloading JARs: {stdout} {stderr}') @@ -51,11 +28,7 @@ def download_jars(): class BuildPyCommand(build_py): def run(self): - try: - download_jars() - except: - print('Could not download JARs using Maven, falling back to GitHub') - fallback_download_jars() + download_jars() super().run() From 65932234544f87ec1cd5697b4f6156def7cb143d Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 20:18:16 +0200 Subject: [PATCH 048/154] Fix setup debug info --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index e857ff3..dccb13f 100644 --- a/setup.py +++ b/setup.py @@ -16,14 +16,14 @@ def download_jars(): proc = subprocess.Popen(MAVEN_EXECUTABLE + ['-version'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) stdout, stderr = proc.communicate() if proc.returncode != 0: - raise RuntimeError(f'Could not run mvn.cmd: {stderr}') + raise RuntimeError(f'Could not run mvn:\n{stdout}\n{stderr}') if 'Apache Maven' not in stdout: raise RuntimeError(f'Could not find Apache Maven in {stdout}') print('Downloading JARs...') proc = subprocess.Popen(MAVEN_EXECUTABLE + ['dependency:copy-dependencies', f'-DoutputDirectory={JAR_FOLDER}'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd=Path(__file__).parent) stdout, stderr = proc.communicate() if proc.returncode != 0: - raise RuntimeError(f'Error while downloading JARs: {stdout} {stderr}') + raise RuntimeError(f'Error while downloading JARs:\n{stdout}\n{stderr}') class BuildPyCommand(build_py): From fe6c17fba00ad8d86e3b4e98418a03ac4397506e Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 20:20:18 +0200 Subject: [PATCH 049/154] Delete obsolete workflow files --- .github/workflows/deploy.yml | 57 ------------------------------- .github/workflows/quick-check.yml | 39 --------------------- 2 files changed, 96 deletions(-) delete mode 100644 .github/workflows/deploy.yml delete mode 100644 .github/workflows/quick-check.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index f170475..0000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: deploy -on: - push: -# tags: -# - '[0-9]+.[0-9]+.[0-9]+' - branches: - - develop - - master -env: - project-name: 2PPy - workflow: deploy -jobs: - deploy-on-pypi: - runs-on: ubuntu-latest - steps: - - name: Show Env - run: | - python --version - pip --version - java --version - javac --version - - - name: Checkout code - uses: actions/checkout@v3 - with: - fetch-depth: 0 # all history - - - name: Get All Tags - run: git fetch --tags -f - - - name: Restore Python dependencies - run: pip install -r requirements.txt - - - name: Restore JVM dependencies - run: ./download-jars.sh - - - name: Test - run: python -m unittest - - - name: Change default logging level - run: sed -i -e 's/DEBUG/WARN/g' tuprolog/__init__.py - - - name: Pack - run: python -m build - - - name: Archive Dist Artifacts - if: failure() || success() - uses: actions/upload-artifact@v3 - with: - name: dist - path: './dist' - - - name: Upload - run: python -m twine upload dist/* - env: - TWINE_USERNAME: ${{ secrets.PYPI_USERANAME }} - TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} diff --git a/.github/workflows/quick-check.yml b/.github/workflows/quick-check.yml deleted file mode 100644 index 3589ec7..0000000 --- a/.github/workflows/quick-check.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: quick-check -on: - push: - branches: - - master - - develop - - 'feature/**' -env: - # jdk-version: openjdk@~1.15.0 - project-name: 2PPy - workflow: quick-check - # gradle-options: "--no-daemon --console=plain --stacktrace" -jobs: - run-unit-tests: - runs-on: ubuntu-latest - steps: - - name: Show Env - run: | - python --version - pip --version - java --version - javac --version - - - name: Checkout code - uses: actions/checkout@v3 - with: - fetch-depth: 0 # all history - - # - name: Get All Tags - # run: git fetch --tags -f - - - name: Restore Python dependencies - run: pip install -r requirements.txt - - - name: Restore JVM dependencies - run: ./download-jars.sh - - - name: Test - run: python -m unittest From b078ed02348d3a887d97e41a3e46293c8cac9fbc Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 20:22:47 +0200 Subject: [PATCH 050/154] Use -v for maven version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index dccb13f..5a26ade 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ def download_jars(): print('Checking Maven...') - proc = subprocess.Popen(MAVEN_EXECUTABLE + ['-version'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + proc = subprocess.Popen(MAVEN_EXECUTABLE + ['-v'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) stdout, stderr = proc.communicate() if proc.returncode != 0: raise RuntimeError(f'Could not run mvn:\n{stdout}\n{stderr}') From 5c9a65731ea75757239beb4c53a574b01724332f Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 20:30:42 +0200 Subject: [PATCH 051/154] Attempt to fix the no goal error on unix systems --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 5a26ade..9f0e68a 100644 --- a/setup.py +++ b/setup.py @@ -13,14 +13,14 @@ def download_jars(): print('Checking Maven...') - proc = subprocess.Popen(MAVEN_EXECUTABLE + ['-v'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + proc = subprocess.Popen(args=MAVEN_EXECUTABLE + ['-v', 'help:help'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) stdout, stderr = proc.communicate() if proc.returncode != 0: raise RuntimeError(f'Could not run mvn:\n{stdout}\n{stderr}') if 'Apache Maven' not in stdout: raise RuntimeError(f'Could not find Apache Maven in {stdout}') print('Downloading JARs...') - proc = subprocess.Popen(MAVEN_EXECUTABLE + ['dependency:copy-dependencies', f'-DoutputDirectory={JAR_FOLDER}'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd=Path(__file__).parent) + proc = subprocess.Popen(args=MAVEN_EXECUTABLE + ['dependency:copy-dependencies', f'-DoutputDirectory={JAR_FOLDER}'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd=Path(__file__).parent) stdout, stderr = proc.communicate() if proc.returncode != 0: raise RuntimeError(f'Error while downloading JARs:\n{stdout}\n{stderr}') From 317604e6c1b72753068eab92cb9e75f301e5724c Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 20:32:12 +0200 Subject: [PATCH 052/154] Use LTS java versions --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b084d4..b37fba2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: matrix: os: [ubuntu, windows, macos] python-version: ['3.9', '3.10', '3.11'] - java-version: ['11', '16', '18'] + java-version: ['11', '17', '20'] fail-fast: false runs-on: ${{ matrix.os }}-latest steps: From c44a4860a4b23a5a500a51c3bb5bdef40adf486c Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 20:42:40 +0200 Subject: [PATCH 053/154] Use shell mode only for windows --- setup.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 9f0e68a..a3c7999 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,5 @@ import os +import platform import jdk import subprocess from pathlib import Path @@ -11,16 +12,20 @@ MAVEN_EXECUTABLE = ['mvn', '--batch-mode'] +def is_windows(): + return platform.system() == 'Windows' + + def download_jars(): print('Checking Maven...') - proc = subprocess.Popen(args=MAVEN_EXECUTABLE + ['-v', 'help:help'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + proc = subprocess.Popen(MAVEN_EXECUTABLE + ['-v'], shell=is_windows(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) stdout, stderr = proc.communicate() if proc.returncode != 0: raise RuntimeError(f'Could not run mvn:\n{stdout}\n{stderr}') if 'Apache Maven' not in stdout: raise RuntimeError(f'Could not find Apache Maven in {stdout}') print('Downloading JARs...') - proc = subprocess.Popen(args=MAVEN_EXECUTABLE + ['dependency:copy-dependencies', f'-DoutputDirectory={JAR_FOLDER}'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd=Path(__file__).parent) + proc = subprocess.Popen(MAVEN_EXECUTABLE + ['dependency:copy-dependencies', f'-DoutputDirectory={JAR_FOLDER}'], shell=is_windows(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd=Path(__file__).parent) stdout, stderr = proc.communicate() if proc.returncode != 0: raise RuntimeError(f'Error while downloading JARs:\n{stdout}\n{stderr}') From 7d3d4b987a2622c9b454dd50bbf95c83be289314 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 20:44:31 +0200 Subject: [PATCH 054/154] Remove Java 20 as it's not available --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b37fba2..683b65b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: matrix: os: [ubuntu, windows, macos] python-version: ['3.9', '3.10', '3.11'] - java-version: ['11', '17', '20'] + java-version: ['11', '17'] fail-fast: false runs-on: ${{ matrix.os }}-latest steps: From 0e107d5f73b9259e31ba84bcad1ac04d907e7a19 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 20:54:13 +0200 Subject: [PATCH 055/154] Replace java 17 with 18 to fix access violations --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 683b65b..c1734f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: matrix: os: [ubuntu, windows, macos] python-version: ['3.9', '3.10', '3.11'] - java-version: ['11', '17'] + java-version: ['11', '18'] fail-fast: false runs-on: ${{ matrix.os }}-latest steps: From b0d01b4f14c48b989395251dc0bb9dbbfe521285 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 4 Apr 2023 21:00:59 +0200 Subject: [PATCH 056/154] Use Java 17 anyway and java 11 for the build artifact --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1734f1..aaa8a24 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: matrix: os: [ubuntu, windows, macos] python-version: ['3.9', '3.10', '3.11'] - java-version: ['11', '18'] + java-version: ['11', '17'] fail-fast: false runs-on: ${{ matrix.os }}-latest steps: @@ -85,7 +85,7 @@ jobs: - name: Download Artifacts uses: actions/download-artifact@v3 with: - name: ${{ env.project-name }}-3.11-ubuntu-java18 + name: ${{ env.project-name }}-3.11-ubuntu-java11 - name: List files run: | ls -lah From 83bca7cddd1aa5cd06dc7300ab44cd009f71ab63 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 5 Apr 2023 11:13:37 +0200 Subject: [PATCH 057/154] Add license to artifacts --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aaa8a24..61b9cf9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,6 +61,7 @@ jobs: path: | dist/*.whl dist/*.tar.gz + LICENSE lint: runs-on: ubuntu-latest From cd9206b413ec0a7a224c0b80c26abec3b1c8bba8 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 5 Apr 2023 11:14:51 +0200 Subject: [PATCH 058/154] Drop python < 3.9 --- pyproject.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 55a9678..3fe3dc0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,9 +22,6 @@ classifiers=[ "Topic :: Scientific/Engineering :: Artificial Intelligence", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", From de3c3d2cb63e0836625c3d15e83c2cd677d91158 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 5 Apr 2023 14:06:04 +0200 Subject: [PATCH 059/154] Retrieve all git history to compute version --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 61b9cf9..7e4dd7d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,6 +26,8 @@ jobs: runs-on: ${{ matrix.os }}-latest steps: - uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: From 19f929ba20dd8e995f509ccb3499fd470e3709e8 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 5 Apr 2023 14:15:34 +0200 Subject: [PATCH 060/154] Bundle LICENSE with other artifacts --- .github/workflows/ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7e4dd7d..3955af7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,9 @@ jobs: - name: Test run: | python -m pytest + - name: Prepare artifacts + run: | + cp LICENSE dist/ - name: Upload artifacts uses: actions/upload-artifact@v3 with: @@ -63,7 +66,7 @@ jobs: path: | dist/*.whl dist/*.tar.gz - LICENSE + dist/LICENSE lint: runs-on: ubuntu-latest From d4c533fe09da9fee526034dbf056718161e9c399 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 5 Apr 2023 16:21:50 +0200 Subject: [PATCH 061/154] Refactor ci/cd --- .github/workflows/ci.yml | 29 +++++++++++++++++++++++++---- requirements.txt | 2 +- setup.py | 6 ------ 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3955af7..98c62c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,8 @@ on: env: project-name: 2PPy + python-version: '3.11' + java-version: '11' defaults: run: @@ -22,8 +24,17 @@ jobs: os: [ubuntu, windows, macos] python-version: ['3.9', '3.10', '3.11'] java-version: ['11', '17'] + include: + - package: false + - os: ubuntu + python-version: ${{ env.python-version }} + java-version: ${{ env.java-version }} + package: true fail-fast: false runs-on: ${{ matrix.os }}-latest + outputs: + artifact-name: ${{ steps.artifact.outputs.artifact-name }} + version: ${{ steps.artifact.outputs.version }} steps: - uses: actions/checkout@v3 with: @@ -42,8 +53,7 @@ jobs: cache: maven - name: Install dependencies run: | - python -m pip install --upgrade pip setuptools wheel - pip install pytest + python -m pip install --upgrade pip setuptools wheel build if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Build env: @@ -57,12 +67,18 @@ jobs: run: | python -m pytest - name: Prepare artifacts + id: artifact + if: ${{ matrix.package }} run: | cp LICENSE dist/ + echo 'artifact-name=${{ env.project-name }}-${{ matrix.python-version }}-${{ matrix.os }}-java${{ matrix.java-version }}' >> "$GITHUB_OUTPUT"' + VERSION=$(python setup.py --version) + echo "version=$VERSION" >> "$GITHUB_OUTPUT" - name: Upload artifacts + if: ${{ matrix.package }} uses: actions/upload-artifact@v3 with: - name: ${{ env.project-name }}-${{ matrix.python-version }}-${{ matrix.os }}-java${{ matrix.java-version }} + name: ${{ steps.artifact.outputs.artifact-name }} path: | dist/*.whl dist/*.tar.gz @@ -87,11 +103,16 @@ jobs: delivery: runs-on: ubuntu-latest needs: [build, lint] + concurrency: + group: release steps: - name: Download Artifacts uses: actions/download-artifact@v3 with: - name: ${{ env.project-name }}-3.11-ubuntu-java11 + name: ${{ needs.build.outputs.artifact-name }} - name: List files run: | ls -lah + - name: Print version + run: | + echo '${{ needs.build.outputs.version }}'' diff --git a/requirements.txt b/requirements.txt index c694340..bf23b94 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -build==0.10.0 flake8==6.0.0 +pytest==7.2.2 diff --git a/setup.py b/setup.py index a3c7999..3461a87 100644 --- a/setup.py +++ b/setup.py @@ -17,14 +17,12 @@ def is_windows(): def download_jars(): - print('Checking Maven...') proc = subprocess.Popen(MAVEN_EXECUTABLE + ['-v'], shell=is_windows(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) stdout, stderr = proc.communicate() if proc.returncode != 0: raise RuntimeError(f'Could not run mvn:\n{stdout}\n{stderr}') if 'Apache Maven' not in stdout: raise RuntimeError(f'Could not find Apache Maven in {stdout}') - print('Downloading JARs...') proc = subprocess.Popen(MAVEN_EXECUTABLE + ['dependency:copy-dependencies', f'-DoutputDirectory={JAR_FOLDER}'], shell=is_windows(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd=Path(__file__).parent) stdout, stderr = proc.communicate() if proc.returncode != 0: @@ -39,16 +37,12 @@ def run(self): def install_java(): if JAVA_FOLDER.exists(): - print('Java already installed') return java_version = os.getenv('JAVA_VERSION', '11') destination_folder = str(JAR_FOLDER) - print(f'Downloading Java {java_version} in {destination_folder}...') installation_path = Path(jdk.install(java_version, jre=not java_version.startswith('16'), path=destination_folder)) destination_folder = JAVA_FOLDER - print(f'Installing Java in {destination_folder}...') installation_path = installation_path.rename(destination_folder) - print(f'Installed Java in {installation_path}') install_java() From abe9814d242848e6a975649327d17a2568db7a9e Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 5 Apr 2023 16:27:12 +0200 Subject: [PATCH 062/154] Fix ci --- .github/workflows/ci.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98c62c3..7c0a115 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,8 +10,6 @@ on: env: project-name: 2PPy - python-version: '3.11' - java-version: '11' defaults: run: @@ -27,8 +25,8 @@ jobs: include: - package: false - os: ubuntu - python-version: ${{ env.python-version }} - java-version: ${{ env.java-version }} + python-version: '3.9' + java-version: '11' package: true fail-fast: false runs-on: ${{ matrix.os }}-latest From 2aa8db019ea4aeedfaf76245c2292f3209075bb7 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 5 Apr 2023 16:29:46 +0200 Subject: [PATCH 063/154] Fix ci --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c0a115..1397aba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,7 +69,7 @@ jobs: if: ${{ matrix.package }} run: | cp LICENSE dist/ - echo 'artifact-name=${{ env.project-name }}-${{ matrix.python-version }}-${{ matrix.os }}-java${{ matrix.java-version }}' >> "$GITHUB_OUTPUT"' + echo 'artifact-name=${{ env.project-name }}-${{ matrix.python-version }}-${{ matrix.os }}-java${{ matrix.java-version }}' >> "$GITHUB_OUTPUT" VERSION=$(python setup.py --version) echo "version=$VERSION" >> "$GITHUB_OUTPUT" - name: Upload artifacts From cb747258884b5c585f46d012051ffc9ef02fe57b Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 5 Apr 2023 17:16:28 +0200 Subject: [PATCH 064/154] Fic ci & requirements --- .github/workflows/ci.yml | 10 ++++++---- requirements.txt | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1397aba..dc54fae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,10 +49,9 @@ jobs: distribution: 'adopt' architecture: 'x64' cache: maven - - name: Install dependencies + - name: Install build tool run: | - python -m pip install --upgrade pip setuptools wheel build - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + python -m pip install --upgrade pip build - name: Build env: JAVA_VERSION: ${{ matrix.java-version }} @@ -61,6 +60,9 @@ jobs: - name: Install run: | pip install dist/*.whl + - name: Install CI dependencies + run: | + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Test run: | python -m pytest @@ -70,7 +72,7 @@ jobs: run: | cp LICENSE dist/ echo 'artifact-name=${{ env.project-name }}-${{ matrix.python-version }}-${{ matrix.os }}-java${{ matrix.java-version }}' >> "$GITHUB_OUTPUT" - VERSION=$(python setup.py --version) + VERSION=$(python -m setuptools_git_versioning) echo "version=$VERSION" >> "$GITHUB_OUTPUT" - name: Upload artifacts if: ${{ matrix.package }} diff --git a/requirements.txt b/requirements.txt index bf23b94..684cd5b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,4 @@ +# CI & Test dependencies flake8==6.0.0 pytest==7.2.2 +setuptools-git-versioning==1.13.3 From a976d4da4d57919b4621217cb97605cb9ab3bbb4 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 5 Apr 2023 17:20:36 +0200 Subject: [PATCH 065/154] Fix missing requirement for ci --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 684cd5b..688ce45 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ flake8==6.0.0 pytest==7.2.2 setuptools-git-versioning==1.13.3 +install-jdk==1.0.2 From 3ba0d6791f95aa02835dbf5ed3a26721ea99a3a6 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 5 Apr 2023 17:57:03 +0200 Subject: [PATCH 066/154] Add publish job to ci --- .github/workflows/ci.yml | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dc54fae..308f250 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -105,14 +105,37 @@ jobs: needs: [build, lint] concurrency: group: release + if: ${{ startsWith(github.ref, 'refs/tags/') && github.event_name == 'push' }} steps: - name: Download Artifacts uses: actions/download-artifact@v3 with: name: ${{ needs.build.outputs.artifact-name }} - - name: List files - run: | - ls -lah - - name: Print version - run: | - echo '${{ needs.build.outputs.version }}'' + - name: GitHub Release + uses: softprops/action-gh-release@v1 + with: + name: ${{ needs.build.outputs.version }} + fail_on_unmatched_files: true + files: | + *.whl + *.tar.gz + LICENSE + + publish: + runs-on: ubuntu-latest + needs: [build, delivery] + concurrency: + group: publish + environment: test-pypi + steps: + - name: Download Artifacts + uses: actions/download-artifact@v3 + with: + name: ${{ needs.build.outputs.artifact-name }} + working-directory: dist + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + password: ${{ secrets.TEST_PYPI_TOKEN }} + repository-url: https://test.pypi.org/legacy/ + packages-dir: dist From de7e59ac6d50c93456e7c94aed544c543d853e61 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 5 Apr 2023 20:22:49 +0200 Subject: [PATCH 067/154] Merge master into develop and fix tests --- .github/workflows/ci.yml | 2 +- test/core/test_kt_math.py | 6 ------ tuprolog/core/__init__.py | 2 +- tuprolog/core/_ktmath.py | 12 +----------- 4 files changed, 3 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 308f250..5fa5d59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,7 +65,7 @@ jobs: if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Test run: | - python -m pytest + python -m pytest -p no:faulthandler - name: Prepare artifacts id: artifact if: ${{ matrix.package }} diff --git a/test/core/test_kt_math.py b/test/core/test_kt_math.py index 1c73305..48bbacd 100644 --- a/test/core/test_kt_math.py +++ b/test/core/test_kt_math.py @@ -118,9 +118,6 @@ def test_python_to_java_one_cent(self): self.assertSameStringRepresentation(0.01, big_decimal("0.01")) self.assertSameStringRepresentation(0.01, big_decimal("0.010")) self.assertSameStringRepresentation(0.01, big_decimal("0.0100")) - self.assertSameStringRepresentation(0.01, big_decimal(0.01)) - self.assertSameStringRepresentation(0.01, big_decimal(0.010)) - self.assertSameStringRepresentation(0.01, big_decimal(0.0100)) self.assertSameStringRepresentation(self.one_tenth, big_decimal(Decimal(0.01))) self.assertSameStringRepresentation(self.one_tenth, big_decimal(Decimal(0.010))) self.assertSameStringRepresentation(self.one_tenth, big_decimal(Decimal(0.0100))) @@ -173,9 +170,6 @@ def test_java_to_python_one_cent(self): self.assertSameStringRepresentation(Decimal("0.01"), python_decimal(big_decimal("0.01"))) self.assertSameStringRepresentation(Decimal("0.01"), python_decimal(big_decimal("0.010"))) self.assertSameStringRepresentation(Decimal("0.01"), python_decimal(big_decimal("0.0100"))) - self.assertSameStringRepresentation(Decimal("0.01"), python_decimal(big_decimal(0.01))) - self.assertSameStringRepresentation(Decimal("0.01"), python_decimal(big_decimal(0.010))) - self.assertSameStringRepresentation(Decimal("0.01"), python_decimal(big_decimal(0.0100))) self.assertSameStringRepresentation(Decimal(self.one_tenth), python_decimal(big_decimal(Decimal(0.01)))) self.assertSameStringRepresentation(Decimal(self.one_tenth), python_decimal(big_decimal(Decimal(0.010)))) self.assertSameStringRepresentation(Decimal(self.one_tenth), python_decimal(big_decimal(Decimal(0.0100)))) diff --git a/tuprolog/core/__init__.py b/tuprolog/core/__init__.py index 4724b03..d7e389e 100644 --- a/tuprolog/core/__init__.py +++ b/tuprolog/core/__init__.py @@ -190,7 +190,7 @@ def scope(*variables: Union[Var, str]) -> Scope: if len(variables) == 0: return Scope.empty() vars = [var(v) if isinstance(v, str) else v for v in variables] - return Scope.of(jpype.JArray(Var) @ vars) + return Scope.of(vars[0], jpype.JArray(Var) @ vars[1:]) def variables(*names: str) -> PyTuple[Var]: diff --git a/tuprolog/core/_ktmath.py b/tuprolog/core/_ktmath.py index 0265f8b..c225b23 100644 --- a/tuprolog/core/_ktmath.py +++ b/tuprolog/core/_ktmath.py @@ -49,15 +49,6 @@ BIG_DECIMAL_PI = BigDecimal.PI -def _int_to_bytes(n: int) -> bytes: - try: - size = n.bit_length() // 8 + 1 - return n.to_bytes(size, 'big', signed=True) - except OverflowError as e: - e.args = ["%s: %d, whose size is %d" % (e.args[0], n, size)] - raise e - - def big_integer(value: Union[str, int], radix: int = None) -> BigInteger: if radix is not None: assert isinstance(value, str) @@ -65,8 +56,7 @@ def big_integer(value: Union[str, int], radix: int = None) -> BigInteger: if isinstance(value, str): return BigInteger.of(jpype.JString @ value) assert isinstance(value, int) - bs = _int_to_bytes(value) - return BigInteger(jpype.JArray(jpype.JByte) @ bs, 0, len(bs)) + return BigInteger.of(str(value)) def python_integer(value: BigInteger) -> int: From 8dece2db36575a57ee49872690fba36234683e9e Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 5 Apr 2023 20:37:10 +0200 Subject: [PATCH 068/154] Fix ci --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5fa5d59..289870d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -132,7 +132,7 @@ jobs: uses: actions/download-artifact@v3 with: name: ${{ needs.build.outputs.artifact-name }} - working-directory: dist + path: dist - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: From 9aec05be08b1a52e0e0ef5279aaa6afb4e9296e8 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 5 Apr 2023 20:45:14 +0200 Subject: [PATCH 069/154] Fix ci --- .github/workflows/ci.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 289870d..9cc748a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,7 +70,6 @@ jobs: id: artifact if: ${{ matrix.package }} run: | - cp LICENSE dist/ echo 'artifact-name=${{ env.project-name }}-${{ matrix.python-version }}-${{ matrix.os }}-java${{ matrix.java-version }}' >> "$GITHUB_OUTPUT" VERSION=$(python -m setuptools_git_versioning) echo "version=$VERSION" >> "$GITHUB_OUTPUT" @@ -82,7 +81,7 @@ jobs: path: | dist/*.whl dist/*.tar.gz - dist/LICENSE + LICENSE lint: runs-on: ubuntu-latest @@ -100,7 +99,7 @@ jobs: # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide python -m flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - delivery: + release: runs-on: ubuntu-latest needs: [build, lint] concurrency: @@ -117,8 +116,8 @@ jobs: name: ${{ needs.build.outputs.version }} fail_on_unmatched_files: true files: | - *.whl - *.tar.gz + dist/*.whl + dist/*.tar.gz LICENSE publish: @@ -132,7 +131,6 @@ jobs: uses: actions/download-artifact@v3 with: name: ${{ needs.build.outputs.artifact-name }} - path: dist - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: From e9460bc713cbeb76e3c30d95808d88ef78ba9f86 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 5 Apr 2023 20:46:09 +0200 Subject: [PATCH 070/154] Rely on default = dist --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9cc748a..6ec5c57 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -136,4 +136,3 @@ jobs: with: password: ${{ secrets.TEST_PYPI_TOKEN }} repository-url: https://test.pypi.org/legacy/ - packages-dir: dist From 6f30c2b6229902633a4bc2bc3688d7b7c671c3e4 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 5 Apr 2023 20:46:59 +0200 Subject: [PATCH 071/154] Fix ci --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6ec5c57..e33f668 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -122,7 +122,7 @@ jobs: publish: runs-on: ubuntu-latest - needs: [build, delivery] + needs: [build, release] concurrency: group: publish environment: test-pypi From 6e0d66d4f797ab60420041562b02158eafa4462a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Apr 2023 01:08:50 +0000 Subject: [PATCH 072/154] Bump install-jdk from 1.0.2 to 1.0.4 Bumps [install-jdk](https://github.com/jyksnw/install-jdk) from 1.0.2 to 1.0.4. - [Release notes](https://github.com/jyksnw/install-jdk/releases) - [Commits](https://github.com/jyksnw/install-jdk/compare/1.0.2...v1.0.4) --- updated-dependencies: - dependency-name: install-jdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 688ce45..b9e2ff1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,4 @@ flake8==6.0.0 pytest==7.2.2 setuptools-git-versioning==1.13.3 -install-jdk==1.0.2 +install-jdk==1.0.4 From 5cd7136a722b823cb407516a953bb9db8b27d87d Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 14:09:45 +0200 Subject: [PATCH 073/154] install java if not present on first import --- pyproject.toml | 5 +++-- setup.py | 31 +++++++++++++++++-------------- tuprolog/__init__.py | 13 +++++++++---- tuprolog/libs/__init__.py | 11 +++++++++++ 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3fe3dc0..a259df2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools>=61", "wheel", "setuptools-git-versioning<2", "install-jdk<2"] +requires = ["setuptools>=61", "wheel", "setuptools-git-versioning<2", "install-jdk==1.0.4"] build-backend = "setuptools.build_meta" [tool.setuptools-git-versioning] @@ -31,7 +31,8 @@ classifiers=[ license = {file = "LICENSE"} keywords = ["prolog", "symbolic ai", "ecosystem", "tuprolog", "2p", "python"] dependencies = [ - "JPype1~=1.4.1", + "JPype1==1.4.1", + "install-jdk==1.0.4" ] [project.urls] diff --git a/setup.py b/setup.py index 3461a87..63746f4 100644 --- a/setup.py +++ b/setup.py @@ -1,14 +1,15 @@ -import os import platform -import jdk import subprocess +import sys +import importlib.util from pathlib import Path from setuptools import setup from setuptools.command.build_py import build_py +from setuptools.command.install import install -JAR_FOLDER = Path('tuprolog', 'libs') -JAVA_FOLDER = JAR_FOLDER / 'java' +PACKAGE_NAME = 'tuprolog' +JAR_FOLDER = Path(PACKAGE_NAME, 'libs') MAVEN_EXECUTABLE = ['mvn', '--batch-mode'] @@ -35,19 +36,21 @@ def run(self): super().run() -def install_java(): - if JAVA_FOLDER.exists(): - return - java_version = os.getenv('JAVA_VERSION', '11') - destination_folder = str(JAR_FOLDER) - installation_path = Path(jdk.install(java_version, jre=not java_version.startswith('16'), path=destination_folder)) - destination_folder = JAVA_FOLDER - installation_path = installation_path.rename(destination_folder) +class InstallCommand(install): + def run(self): + install.run(self) + def _post_install(): + spec = importlib.util.spec_from_file_location(PACKAGE_NAME, JAR_FOLDER / '__init__.py') + lib = importlib.util.module_from_spec(spec) + sys.modules[spec.name] = lib + spec.loader.exec_module(lib) + lib.install_java_if_missing() + _post_install() -install_java() setup( cmdclass={ - 'build_py': BuildPyCommand + 'build_py': BuildPyCommand, + 'install': InstallCommand, } ) diff --git a/tuprolog/__init__.py b/tuprolog/__init__.py index 50aec61..ddda4f6 100644 --- a/tuprolog/__init__.py +++ b/tuprolog/__init__.py @@ -1,18 +1,23 @@ -import os +import platform import logging # noinspection PyUnresolvedReferences import jpype import jpype.imports -from .libs import JAVA_HOME, CLASSPATH -os.environ['JAVA_HOME'] = str(JAVA_HOME) +from .libs import JAVA_HOME, CLASSPATH, install_java_if_missing + +if platform.system() == 'Windows': + jvmpath = JAVA_HOME / 'bin' / 'server' / 'jvm.dll' +else: + jvmpath = JAVA_HOME / 'lib' / 'server' / 'libjvm.so' logger = logging.getLogger('tuprolog') jars = [str(j.resolve()) for j in CLASSPATH.glob('*.jar')] if not jpype.isJVMStarted(): - jpype.startJVM(classpath=jars) + install_java_if_missing() + jpype.startJVM(jvmpath=str(jvmpath), classpath=jars) # noinspection PyUnresolvedReferences from it.unibo import tuprolog as _tuprolog diff --git a/tuprolog/libs/__init__.py b/tuprolog/libs/__init__.py index d5f08e9..4dd3ed0 100644 --- a/tuprolog/libs/__init__.py +++ b/tuprolog/libs/__init__.py @@ -1,5 +1,16 @@ +import os +import jdk from pathlib import Path JAVA_HOME = Path(__file__).parent / 'java' CLASSPATH = Path(__file__).parent + +def install_java_if_missing(): + if JAVA_HOME.exists(): + return + java_version = os.getenv('JAVA_VERSION', '11') + destination_folder = str(CLASSPATH) + installation_path = Path(jdk.install(java_version, jre=not java_version.startswith('16'), path=destination_folder)) + destination_folder = JAVA_HOME + installation_path = installation_path.rename(destination_folder) From aec4e5b5b8313033de9c4271f5ab3d55af13ffe1 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 14:10:05 +0200 Subject: [PATCH 074/154] Fix term parser factory --- tuprolog/core/parsing/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tuprolog/core/parsing/__init__.py b/tuprolog/core/parsing/__init__.py index 9f68211..4f0cfe5 100644 --- a/tuprolog/core/parsing/__init__.py +++ b/tuprolog/core/parsing/__init__.py @@ -21,9 +21,9 @@ def _factory(source, with_default_operators: bool = True, operators: OperatorSet = None): if operators is None: if with_default_operators: - return source.getWithDefaultOperators() + return source.withDefaultOperators() else: - return source.getWithNoOperator() + return source.withNoOperator() else: if with_default_operators: return source.withOperators(DEFAULT_OPERATORS.plus(operators)) From d864572c9be81b52b2349e6b967a109933a0c67f Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 14:16:05 +0200 Subject: [PATCH 075/154] Fix java installation on macos --- tuprolog/__init__.py | 11 ++++------- tuprolog/libs/__init__.py | 10 +++++++++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/tuprolog/__init__.py b/tuprolog/__init__.py index ddda4f6..cfc65e4 100644 --- a/tuprolog/__init__.py +++ b/tuprolog/__init__.py @@ -1,15 +1,12 @@ -import platform + import logging # noinspection PyUnresolvedReferences import jpype import jpype.imports -from .libs import JAVA_HOME, CLASSPATH, install_java_if_missing +from .libs import JAVA_PATH, CLASSPATH, install_java_if_missing + -if platform.system() == 'Windows': - jvmpath = JAVA_HOME / 'bin' / 'server' / 'jvm.dll' -else: - jvmpath = JAVA_HOME / 'lib' / 'server' / 'libjvm.so' logger = logging.getLogger('tuprolog') @@ -17,7 +14,7 @@ if not jpype.isJVMStarted(): install_java_if_missing() - jpype.startJVM(jvmpath=str(jvmpath), classpath=jars) + jpype.startJVM(jvmpath=str(JAVA_PATH), classpath=jars) # noinspection PyUnresolvedReferences from it.unibo import tuprolog as _tuprolog diff --git a/tuprolog/libs/__init__.py b/tuprolog/libs/__init__.py index 4dd3ed0..ad05d45 100644 --- a/tuprolog/libs/__init__.py +++ b/tuprolog/libs/__init__.py @@ -1,12 +1,20 @@ import os import jdk from pathlib import Path +import platform JAVA_HOME = Path(__file__).parent / 'java' CLASSPATH = Path(__file__).parent -def install_java_if_missing(): +if platform.system() == 'Windows': + JAVA_PATH = JAVA_HOME / 'bin' / 'server' / 'jvm.dll' +elif platform.system() == 'Darwin': + JAVA_PATH = JAVA_HOME / 'lib' / 'server' / 'libjvm.dylib' +else: + JAVA_PATH = JAVA_HOME / 'lib' / 'server' / 'libjvm.so' + +def install_java_if_missing() -> Path: if JAVA_HOME.exists(): return java_version = os.getenv('JAVA_VERSION', '11') From 129f317b83b06bfdcb83642e13540c8a5d27ede2 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 14:46:12 +0200 Subject: [PATCH 076/154] Fix AbstractTermVisitor implementation --- .github/workflows/ci.yml | 33 +++++++++++- main.py | 6 +-- tuprolog/core/__init__.py | 2 + tuprolog/core/visitors.py | 102 ++++++++++++++++++++++++++++++++++++-- 4 files changed, 136 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e33f668..017ae9c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,9 +99,40 @@ jobs: # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide python -m flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + install: + strategy: + matrix: + os: [ubuntu, windows, macos] + python-version: ['3.9', '3.10', '3.11'] + java-version: ['11', '17'] + install: ['wheel', 'sdist'] + fail-fast: false + runs-on: ${{ matrix.os }}-latest + needs: [build] + steps: + - name: Download Artifacts + uses: actions/download-artifact@v3 + with: + name: ${{ needs.build.outputs.artifact-name }} + - name: Install from wheel + if: ${{ matrix.install == 'wheel' }} + run: | + pip install dist/*.whl + - name: Install from sdist + if: ${{ matrix.install == 'sdist' }} + run: | + pip install dist/*.tar.gz + - name: Download main.py + uses: actions/checkout@v3 + with: + path: main.py + - name: Test installation + run: | + python main.py + release: runs-on: ubuntu-latest - needs: [build, lint] + needs: [build, lint, install] concurrency: group: release if: ${{ startsWith(github.ref, 'refs/tags/') && github.event_name == 'push' }} diff --git a/main.py b/main.py index 238b1ac..9f0cf4c 100644 --- a/main.py +++ b/main.py @@ -79,7 +79,7 @@ def visitStruct(self, term): features = map(var, ["A", 'B', 'C', 'D', 'E', 'F']) -weights = map(real, [2.5, -3.4, -0.09, 0.2, 0.0, -2.0]) +weights = map(real, ['2.5', '-3.4', '-0.09', '0.2', '0.0', '-2.0']) x = zip(features, weights) @@ -88,5 +88,5 @@ def visitStruct(self, term): x = foldr(lambda a, b: struct('+', a, b), x) x = struct('is', var('Y'), x) -print(formatter.format(x)) -print(formatter.format(x.accept(Simplifier()))) \ No newline at end of file +assert formatter.format(x) == 'Y is 2.5 * A + -3.4 * B + -0.09 * C + 0.2 * D + -2.0 * F' +assert formatter.format(x.accept(Simplifier())) == 'Y is 2.5 * A - 3.4 * B - 0.09 * C + 0.2 * D - 2.0 * F' diff --git a/tuprolog/core/__init__.py b/tuprolog/core/__init__.py index d7e389e..ef9f942 100644 --- a/tuprolog/core/__init__.py +++ b/tuprolog/core/__init__.py @@ -123,6 +123,8 @@ def integer(value: Union[int, BigInteger, str]) -> Integer: def real(value: Union[float, BigDecimal, str, Decimal]) -> Real: + if isinstance(value, BigDecimal): + return Real.of(value) return Real.of(big_decimal(value)) diff --git a/tuprolog/core/visitors.py b/tuprolog/core/visitors.py index bec3593..90a99fd 100644 --- a/tuprolog/core/visitors.py +++ b/tuprolog/core/visitors.py @@ -2,8 +2,104 @@ import jpype # noinspection PyUnresolvedReferences import jpype.imports -import it.unibo.tuprolog.core.visitors as _visitors +import it.unibo.tuprolog.core as _core -DefaultTermVisitor = _visitors.DefaultTermVisitor +TermVisitor = _core.TermVisitor -logger.debug("Loaded compatibility layer for JVM subtypes of " + str(DefaultTermVisitor.class_.getName())) +@jpype.JImplements(TermVisitor) +class AbstractTermVisitor(object): + + @jpype.JOverride + def defaultValue(self, term): + raise NotImplementedError() + + @jpype.JOverride + def visitTerm(self, term): + return TermVisitor.visitTerm(self, term) + + @jpype.JOverride + def visitVar(self, term): + return TermVisitor.visitVar(self, term) + + @jpype.JOverride + def visitConstant(self, term): + return TermVisitor.visitConstant(self, term) + + @jpype.JOverride + def visitStruct(self, term): + return TermVisitor.visitStruct(self, term) + + @jpype.JOverride + def visitCollection(self, term): + return TermVisitor.visitCollection(self, term) + + @jpype.JOverride + def visitAtom(self, term): + return TermVisitor.visitAtom(self, term) + + @jpype.JOverride + def visitTruth(self, term): + return TermVisitor.visitTruth(self, term) + + @jpype.JOverride + def visitNumeric(self, term): + return TermVisitor.visitNumeric(self, term) + + @jpype.JOverride + def visitInteger(self, term): + return TermVisitor.visitInteger(self, term) + + @jpype.JOverride + def visitReal(self, term): + return TermVisitor.visitReal(self, term) + + @jpype.JOverride + def visitBlock(self, term): + return TermVisitor.visitBlock(self, term) + + @jpype.JOverride + def visitEmpty(self, term): + return TermVisitor.visitEmpty(self, term) + + @jpype.JOverride + def visitEmptyBlock(self, term): + return TermVisitor.visitEmptyBlock(self, term) + + @jpype.JOverride + def visitList(self, term): + return TermVisitor.visitList(self, term) + + @jpype.JOverride + def visitCons(self, term): + return TermVisitor.visitCons(self, term) + + @jpype.JOverride + def visitEmptyList(self, term): + return TermVisitor.visitEmptyList(self, term) + + @jpype.JOverride + def visitTuple(self, term): + return TermVisitor.visitTuple(self, term) + + @jpype.JOverride + def visitIndicator(self, term): + return TermVisitor.visitIndicator(self, term) + + @jpype.JOverride + def visitClause(self, term): + return TermVisitor.visitClause(self, term) + + @jpype.JOverride + def visitRule(self, term): + return TermVisitor.visitRule(self, term) + + @jpype.JOverride + def visitFact(self, term): + return TermVisitor.visitFact(self, term) + + @jpype.JOverride + def visitDirective(self, term): + return TermVisitor.visitDirective(self, term) + + +logger.debug("Loaded compatibility layer for JVM subtypes of " + str(TermVisitor.class_.getName())) From ee576501a6d0cc0007c86f9896c30e8853632184 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 14:51:18 +0200 Subject: [PATCH 077/154] Fix test --- test/core/test_visitors.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/test/core/test_visitors.py b/test/core/test_visitors.py index 0890237..c2ecbf2 100644 --- a/test/core/test_visitors.py +++ b/test/core/test_visitors.py @@ -1,23 +1,21 @@ import unittest from tuprolog.core import * -from tuprolog.core.visitors import DefaultTermVisitor +from tuprolog.core.visitors import AbstractTermVisitor import jpype.imports import kotlin.jvm.functions as _functions -@jpype.JImplements(_functions.Function1) -class Lambda: - def __init__(self, f): - self.f = f - - @jpype.JOverride - def invoke(self, arg): - return self.f(arg) +import unittest +from tuprolog.core import * +from tuprolog.core.visitors import AbstractTermVisitor class TestVisitors(unittest.TestCase): def test_term_visitor(self): - visitor = DefaultTermVisitor.of(Lambda(lambda term: 'a')) + class MyVisitor(AbstractTermVisitor): + def defaultValue(self, term): + return 'a' + visitor = MyVisitor() for term in [Atom.of('a'), Integer.of(1), Var.of("X")]: self.assertEqual(term.accept(visitor), 'a') From cdc5d2313aac6f04ede46fea6fcc01f636ff354a Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 15:04:13 +0200 Subject: [PATCH 078/154] Attempt to fix macos libjli.dylib location --- tuprolog/libs/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tuprolog/libs/__init__.py b/tuprolog/libs/__init__.py index ad05d45..81d9396 100644 --- a/tuprolog/libs/__init__.py +++ b/tuprolog/libs/__init__.py @@ -10,7 +10,7 @@ if platform.system() == 'Windows': JAVA_PATH = JAVA_HOME / 'bin' / 'server' / 'jvm.dll' elif platform.system() == 'Darwin': - JAVA_PATH = JAVA_HOME / 'lib' / 'server' / 'libjvm.dylib' + JAVA_PATH = JAVA_HOME / 'lib' / 'jli' / 'libjli.dylib' else: JAVA_PATH = JAVA_HOME / 'lib' / 'server' / 'libjvm.so' From 30df99f3d8b94f9589c2312cce2d64cc9f6a0c8a Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 15:07:21 +0200 Subject: [PATCH 079/154] Fix ci --- .github/workflows/ci.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 017ae9c..9eddb75 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -109,7 +109,14 @@ jobs: fail-fast: false runs-on: ${{ matrix.os }}-latest needs: [build] + env: + JAVA_VERSION: ${{ matrix.java-version }} steps: + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + cache: pip - name: Download Artifacts uses: actions/download-artifact@v3 with: From 8288046ca1c7d71f6158535289cedbf99496bc8a Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 15:07:33 +0200 Subject: [PATCH 080/154] Attempt to locate libjli.dylib --- tuprolog/libs/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tuprolog/libs/__init__.py b/tuprolog/libs/__init__.py index 81d9396..20d8d25 100644 --- a/tuprolog/libs/__init__.py +++ b/tuprolog/libs/__init__.py @@ -10,7 +10,7 @@ if platform.system() == 'Windows': JAVA_PATH = JAVA_HOME / 'bin' / 'server' / 'jvm.dll' elif platform.system() == 'Darwin': - JAVA_PATH = JAVA_HOME / 'lib' / 'jli' / 'libjli.dylib' + JAVA_PATH = JAVA_HOME / 'lib' / 'libjli.dylib' else: JAVA_PATH = JAVA_HOME / 'lib' / 'server' / 'libjvm.so' From 805aec77390ca612dfdf54f2d013c6b4b2c06d0d Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 15:11:55 +0200 Subject: [PATCH 081/154] print directory tree after java installation --- tuprolog/libs/__init__.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tuprolog/libs/__init__.py b/tuprolog/libs/__init__.py index 20d8d25..f1ec4a9 100644 --- a/tuprolog/libs/__init__.py +++ b/tuprolog/libs/__init__.py @@ -1,7 +1,8 @@ import os import jdk -from pathlib import Path import platform +from pathlib import Path +from jpype import _jvmfinder JAVA_HOME = Path(__file__).parent / 'java' @@ -12,7 +13,7 @@ elif platform.system() == 'Darwin': JAVA_PATH = JAVA_HOME / 'lib' / 'libjli.dylib' else: - JAVA_PATH = JAVA_HOME / 'lib' / 'server' / 'libjvm.so' + JAVA_PATH = JAVA_HOME / 'lib' / 'server' / 'libjvm.so' def install_java_if_missing() -> Path: if JAVA_HOME.exists(): @@ -22,3 +23,12 @@ def install_java_if_missing() -> Path: installation_path = Path(jdk.install(java_version, jre=not java_version.startswith('16'), path=destination_folder)) destination_folder = JAVA_HOME installation_path = installation_path.rename(destination_folder) + def list_files(startpath): + for root, dirs, files in os.walk(startpath): + level = root.replace(startpath, '').count(os.sep) + indent = ' ' * 4 * (level) + print('{}{}/'.format(indent, os.path.basename(root))) + subindent = ' ' * 4 * (level + 1) + for f in files: + print('{}{}'.format(subindent, f)) + list_files(installation_path) From d78d4ee4124c1a6c00849f33290a01ed866ed449 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 15:22:16 +0200 Subject: [PATCH 082/154] Fix import --- tuprolog/libs/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tuprolog/libs/__init__.py b/tuprolog/libs/__init__.py index f1ec4a9..c3ec555 100644 --- a/tuprolog/libs/__init__.py +++ b/tuprolog/libs/__init__.py @@ -2,7 +2,6 @@ import jdk import platform from pathlib import Path -from jpype import _jvmfinder JAVA_HOME = Path(__file__).parent / 'java' From 9b280def4d00fb74f105480c084cfeeabfd43cb7 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 15:23:45 +0200 Subject: [PATCH 083/154] Fix script --- tuprolog/libs/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tuprolog/libs/__init__.py b/tuprolog/libs/__init__.py index c3ec555..4f946c9 100644 --- a/tuprolog/libs/__init__.py +++ b/tuprolog/libs/__init__.py @@ -11,8 +11,10 @@ JAVA_PATH = JAVA_HOME / 'bin' / 'server' / 'jvm.dll' elif platform.system() == 'Darwin': JAVA_PATH = JAVA_HOME / 'lib' / 'libjli.dylib' -else: +elif platform.system() == 'Linux': JAVA_PATH = JAVA_HOME / 'lib' / 'server' / 'libjvm.so' +else: + raise RuntimeError("Unsupported platform: " + platform.system()) def install_java_if_missing() -> Path: if JAVA_HOME.exists(): @@ -30,4 +32,4 @@ def list_files(startpath): subindent = ' ' * 4 * (level + 1) for f in files: print('{}{}'.format(subindent, f)) - list_files(installation_path) + list_files(str(installation_path)) From c9a49029d9487443b028ff52771df1eb83e4a928 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 15:27:50 +0200 Subject: [PATCH 084/154] Fix darwin jvm location --- tuprolog/libs/__init__.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/tuprolog/libs/__init__.py b/tuprolog/libs/__init__.py index 4f946c9..247dbcf 100644 --- a/tuprolog/libs/__init__.py +++ b/tuprolog/libs/__init__.py @@ -10,7 +10,7 @@ if platform.system() == 'Windows': JAVA_PATH = JAVA_HOME / 'bin' / 'server' / 'jvm.dll' elif platform.system() == 'Darwin': - JAVA_PATH = JAVA_HOME / 'lib' / 'libjli.dylib' + JAVA_PATH = JAVA_HOME / 'Contents' / 'Home' / 'lib' / 'jli' / 'libjli.dylib' elif platform.system() == 'Linux': JAVA_PATH = JAVA_HOME / 'lib' / 'server' / 'libjvm.so' else: @@ -24,12 +24,3 @@ def install_java_if_missing() -> Path: installation_path = Path(jdk.install(java_version, jre=not java_version.startswith('16'), path=destination_folder)) destination_folder = JAVA_HOME installation_path = installation_path.rename(destination_folder) - def list_files(startpath): - for root, dirs, files in os.walk(startpath): - level = root.replace(startpath, '').count(os.sep) - indent = ' ' * 4 * (level) - print('{}{}/'.format(indent, os.path.basename(root))) - subindent = ' ' * 4 * (level + 1) - for f in files: - print('{}{}'.format(subindent, f)) - list_files(str(installation_path)) From ea3d3a8bb0400d36f2e1c93b895b2381ddccc812 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 15:31:16 +0200 Subject: [PATCH 085/154] Overwrite JAVA_HOME environment variable to always point local installation --- tuprolog/__init__.py | 7 +++---- tuprolog/libs/__init__.py | 10 ---------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/tuprolog/__init__.py b/tuprolog/__init__.py index cfc65e4..4af7768 100644 --- a/tuprolog/__init__.py +++ b/tuprolog/__init__.py @@ -1,12 +1,11 @@ - +import os import logging # noinspection PyUnresolvedReferences import jpype import jpype.imports -from .libs import JAVA_PATH, CLASSPATH, install_java_if_missing - - +from .libs import JAVA_HOME, CLASSPATH, install_java_if_missing +os.environ['JAVA_HOME'] = str(JAVA_HOME) logger = logging.getLogger('tuprolog') diff --git a/tuprolog/libs/__init__.py b/tuprolog/libs/__init__.py index 247dbcf..0c93c7f 100644 --- a/tuprolog/libs/__init__.py +++ b/tuprolog/libs/__init__.py @@ -1,21 +1,11 @@ import os import jdk -import platform from pathlib import Path JAVA_HOME = Path(__file__).parent / 'java' CLASSPATH = Path(__file__).parent -if platform.system() == 'Windows': - JAVA_PATH = JAVA_HOME / 'bin' / 'server' / 'jvm.dll' -elif platform.system() == 'Darwin': - JAVA_PATH = JAVA_HOME / 'Contents' / 'Home' / 'lib' / 'jli' / 'libjli.dylib' -elif platform.system() == 'Linux': - JAVA_PATH = JAVA_HOME / 'lib' / 'server' / 'libjvm.so' -else: - raise RuntimeError("Unsupported platform: " + platform.system()) - def install_java_if_missing() -> Path: if JAVA_HOME.exists(): return From ccc91307454394e9ebd1393ac330278ea0399c39 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 15:34:00 +0200 Subject: [PATCH 086/154] Use JAVA_HOME to find java --- tuprolog/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tuprolog/__init__.py b/tuprolog/__init__.py index 4af7768..6b94d87 100644 --- a/tuprolog/__init__.py +++ b/tuprolog/__init__.py @@ -13,7 +13,7 @@ if not jpype.isJVMStarted(): install_java_if_missing() - jpype.startJVM(jvmpath=str(JAVA_PATH), classpath=jars) + jpype.startJVM(classpath=jars) # noinspection PyUnresolvedReferences from it.unibo import tuprolog as _tuprolog From 0d2219db92285bb463926c8e0c3731818f66b5a6 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 15:44:10 +0200 Subject: [PATCH 087/154] Remove pip cache --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9eddb75..3819aa6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -116,7 +116,6 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - cache: pip - name: Download Artifacts uses: actions/download-artifact@v3 with: From 740c783f2df2dda1b7fc5aefcb7d7d9f5d1acc77 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 16:50:24 +0200 Subject: [PATCH 088/154] Fix main.py --- main.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/main.py b/main.py index 9f0cf4c..8a0daf1 100644 --- a/main.py +++ b/main.py @@ -78,15 +78,16 @@ def visitStruct(self, term): return struct(term.getFunctor(), [a.accept(self) for a in args]) -features = map(var, ["A", 'B', 'C', 'D', 'E', 'F']) -weights = map(real, ['2.5', '-3.4', '-0.09', '0.2', '0.0', '-2.0']) +if __name__ == '__main__': + features = map(var, ["A", 'B', 'C', 'D', 'E', 'F']) + weights = map(real, ['2.5', '-3.4', '-0.09', '0.2', '0.0', '-2.0']) -x = zip(features, weights) -x = filter(lambda fw: not is_zero(fw[1]), x) -x = map(lambda fw: struct('*', fw[1], fw[0]), x) -x = foldr(lambda a, b: struct('+', a, b), x) -x = struct('is', var('Y'), x) + x = zip(features, weights) + x = filter(lambda fw: not is_zero(fw[1]), x) + x = map(lambda fw: struct('*', fw[1], fw[0]), x) + x = foldr(lambda a, b: struct('+', a, b), x) + x = struct('is', var('Y'), x) -assert formatter.format(x) == 'Y is 2.5 * A + -3.4 * B + -0.09 * C + 0.2 * D + -2.0 * F' -assert formatter.format(x.accept(Simplifier())) == 'Y is 2.5 * A - 3.4 * B - 0.09 * C + 0.2 * D - 2.0 * F' + assert formatter.format(x) == 'Y is 2.5 * A + -3.4 * B + -0.09 * C + 0.2 * D + -2.0 * F' + assert formatter.format(x.accept(Simplifier())) == 'Y is 2.5 * A - 3.4 * B - 0.09 * C + 0.2 * D - 2.0 * F' From fe3eb8b23cb3605885c69ba3df58fdaf30e08c45 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 17:14:25 +0200 Subject: [PATCH 089/154] Fix ci --- .github/workflows/ci.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3819aa6..0de94ff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -128,10 +128,14 @@ jobs: if: ${{ matrix.install == 'sdist' }} run: | pip install dist/*.tar.gz - - name: Download main.py + - name: Checkout repository in temp directory uses: actions/checkout@v3 with: - path: main.py + path: temp + - name: Pull test file from repository + run: | + cp temp/test.py . + rm -rf temp - name: Test installation run: | python main.py From 1b51f6cb19a1163107bbc2140cc85108553c812b Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 17:19:15 +0200 Subject: [PATCH 090/154] Fix typo --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0de94ff..9fdc4c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -134,7 +134,7 @@ jobs: path: temp - name: Pull test file from repository run: | - cp temp/test.py . + cp temp/main.py . rm -rf temp - name: Test installation run: | From ff5e4d87351b69a67c66408ad50bb1bc3add1c58 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 18:16:31 +0200 Subject: [PATCH 091/154] Re-add problog support --- .github/workflows/ci.yml | 4 ++-- pom.xml | 11 +++++++++++ main.py => test/post_install_test.py | 19 +++++++++---------- ...log_example.py => test_problog_example.py} | 1 - tuprolog/solve/_ktadapt.py | 4 ---- tuprolog/solve/library/__init__.py | 2 ++ tuprolog/solve/problog/__init__.py | 13 +++++++------ 7 files changed, 31 insertions(+), 23 deletions(-) rename main.py => test/post_install_test.py (79%) rename test/solve/problog/{problog_example.py => test_problog_example.py} (99%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9fdc4c9..7eb2d6b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -134,11 +134,11 @@ jobs: path: temp - name: Pull test file from repository run: | - cp temp/main.py . + cp temp/test/post_install_test.py test.py rm -rf temp - name: Test installation run: | - python main.py + python test.py release: runs-on: ubuntu-latest diff --git a/pom.xml b/pom.xml index c208e05..473c314 100644 --- a/pom.xml +++ b/pom.xml @@ -21,5 +21,16 @@ + + it.unibo.tuprolog + solve-problog-jvm + 0.31.1-dev02+0cd8a1ae6 + + + org.jetbrains.kotlin + kotlin-bom + + + diff --git a/main.py b/test/post_install_test.py similarity index 79% rename from main.py rename to test/post_install_test.py index 8a0daf1..9f0cf4c 100644 --- a/main.py +++ b/test/post_install_test.py @@ -78,16 +78,15 @@ def visitStruct(self, term): return struct(term.getFunctor(), [a.accept(self) for a in args]) -if __name__ == '__main__': - features = map(var, ["A", 'B', 'C', 'D', 'E', 'F']) - weights = map(real, ['2.5', '-3.4', '-0.09', '0.2', '0.0', '-2.0']) +features = map(var, ["A", 'B', 'C', 'D', 'E', 'F']) +weights = map(real, ['2.5', '-3.4', '-0.09', '0.2', '0.0', '-2.0']) - x = zip(features, weights) - x = filter(lambda fw: not is_zero(fw[1]), x) - x = map(lambda fw: struct('*', fw[1], fw[0]), x) - x = foldr(lambda a, b: struct('+', a, b), x) - x = struct('is', var('Y'), x) +x = zip(features, weights) +x = filter(lambda fw: not is_zero(fw[1]), x) +x = map(lambda fw: struct('*', fw[1], fw[0]), x) +x = foldr(lambda a, b: struct('+', a, b), x) +x = struct('is', var('Y'), x) - assert formatter.format(x) == 'Y is 2.5 * A + -3.4 * B + -0.09 * C + 0.2 * D + -2.0 * F' - assert formatter.format(x.accept(Simplifier())) == 'Y is 2.5 * A - 3.4 * B - 0.09 * C + 0.2 * D - 2.0 * F' +assert formatter.format(x) == 'Y is 2.5 * A + -3.4 * B + -0.09 * C + 0.2 * D + -2.0 * F' +assert formatter.format(x.accept(Simplifier())) == 'Y is 2.5 * A - 3.4 * B - 0.09 * C + 0.2 * D - 2.0 * F' diff --git a/test/solve/problog/problog_example.py b/test/solve/problog/test_problog_example.py similarity index 99% rename from test/solve/problog/problog_example.py rename to test/solve/problog/test_problog_example.py index 60e8c4b..1794543 100644 --- a/test/solve/problog/problog_example.py +++ b/test/solve/problog/test_problog_example.py @@ -5,7 +5,6 @@ from tuprolog.solve.problog import problog_solver from tuprolog.solve.problog.operators import PROBLOG_OPERATORS - class ExemplifyProblog(unittest.TestCase): def setUp(self) -> None: diff --git a/tuprolog/solve/_ktadapt.py b/tuprolog/solve/_ktadapt.py index 3854fc1..6433874 100644 --- a/tuprolog/solve/_ktadapt.py +++ b/tuprolog/solve/_ktadapt.py @@ -1,4 +1,3 @@ -from collections import Mapping from itertools import chain from tuprolog import logger @@ -20,9 +19,6 @@ class _KtSolveOptions: _static_keys = {'lazy', 'is_lazy', 'eager', 'is_eager', 'timeout', 'limit'} - def __jclass_init__(self): - Mapping.register(self) - @property def is_lazy(self): return self.isLazy() diff --git a/tuprolog/solve/library/__init__.py b/tuprolog/solve/library/__init__.py index eb09cd7..3178c8d 100644 --- a/tuprolog/solve/library/__init__.py +++ b/tuprolog/solve/library/__init__.py @@ -17,6 +17,8 @@ Pluggable = _library.Pluggable +Runtime = _library.Runtime + def library( alias: str = None, diff --git a/tuprolog/solve/problog/__init__.py b/tuprolog/solve/problog/__init__.py index 5ad628a..64e658c 100644 --- a/tuprolog/solve/problog/__init__.py +++ b/tuprolog/solve/problog/__init__.py @@ -1,16 +1,17 @@ from tuprolog import logger from tuprolog.solve.flags import DEFAULT_FLAG_STORE, FlagStore -from tuprolog.solve.library import libraries, Libraries +from tuprolog.solve.library import libraries, Library, Runtime from tuprolog.solve.channel import InputChannel, OutputChannel, std_out, std_in, std_err, warn -from tuprolog.theory import theory, mutable_theory, Theory +from tuprolog.theory import theory, mutable_theory, Theory, Unificator from tuprolog.solve import Solver, SolverFactory -_PROBLOG_SOLVER_FACTORY = Solver.getProblog() +_PROBLOG_SOLVER_FACTORY = Solver.problog() def problog_solver( - libraries: Libraries = libraries(), + unificator: Unificator = Unificator.getDefault(), + libraries: Library = libraries(), flags: FlagStore = DEFAULT_FLAG_STORE, static_kb: Theory = theory(), dynamic_kb: Theory = mutable_theory(), @@ -22,11 +23,11 @@ def problog_solver( ) -> Solver: if mutable: return _PROBLOG_SOLVER_FACTORY.mutableSolverWithDefaultBuiltins( - libraries, flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning + unificator, Runtime.of(libraries), flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning ) else: return _PROBLOG_SOLVER_FACTORY.solverWithDefaultBuiltins( - libraries, flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning + unificator, Runtime.of(libraries), flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning ) From fb63b42b6446bc7fbf2aaccdb4187ca35bf839a6 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 6 Apr 2023 18:37:58 +0200 Subject: [PATCH 092/154] Fix ci --- .github/workflows/ci.yml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7eb2d6b..4bbdbcc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,6 +82,12 @@ jobs: dist/*.whl dist/*.tar.gz LICENSE + - name: Upload test install script to artifact + if: ${{ matrix.package }} + uses: actions/upload-artifact@v3 + with: + name: test-install-script + path: test/post_install_test.py lint: runs-on: ubuntu-latest @@ -128,17 +134,13 @@ jobs: if: ${{ matrix.install == 'sdist' }} run: | pip install dist/*.tar.gz - - name: Checkout repository in temp directory - uses: actions/checkout@v3 + - name: Pull test file from artifacts + uses: actions/download-artifact@v3 with: - path: temp - - name: Pull test file from repository - run: | - cp temp/test/post_install_test.py test.py - rm -rf temp + name: test-install-script - name: Test installation run: | - python test.py + python post_install_test.py release: runs-on: ubuntu-latest From 33d106cbb682427b9ef98a2a1eec966d41452704 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Fri, 7 Apr 2023 10:28:58 +0200 Subject: [PATCH 093/154] Update README.md --- README.md | 72 +++++++++++++++++++------------------------------------ 1 file changed, 25 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 8d5b57a..7bf28e0 100644 --- a/README.md +++ b/README.md @@ -21,21 +21,21 @@ Object-oriented and modular ecosystem for symbolic AI and logic programming, cur * two serialisation-related modules: one aimed at (de)serialising terms and clauses, namely `tuprolog.core.serialize`, and the other aimed at (de)serialising terms theories, namely `tuprolog.theory.serialize`, -* a module for using Prolog via a command-line interface, namely `tuprolog.repl`. +* a module for using Prolog via a command-line interface, namely `tuprolog.repl`, -## How to do stuff +* a module that implement probabilistic logic programming and solving, namely `tuprolog.solve.problog`. -### Prerequisites +## How to use 2ppy -1. Install Python 3 (look into the `.python-version` to know the exact version) - * I suggest using [Pyenv](https://github.com/pyenv/pyenv) to easily handle multiple Python versions on the same machine - * Ensure PIP works fine - -2. Install Java (JDK preferred), and **ensure the `JAVA_HOME` variable is correctly set** +### Use 2ppy as a library -3. Ensure Java and Python are both either 64bit or 32bit +1. Install Python 3 (look into the `.pyproject.toml` to know the exact versions supported) + * If your system has 64-bit processor, install the Python 3 64-bit distribution, and viceversa + * Ensure PIP works fine + * It's suggested to use a [virtual environment](https://docs.python.org/3/library/venv.html) to install the dependencies locally + * It's suggested to use [Pyenv](https://github.com/pyenv/pyenv) to easily handle multiple Python versions on the same machine -4. If you have installed some prior development version of 2PPy (e.g. `tuppy` or `tuprolog`), uninstall them via +1. If you have installed some prior development version of 2PPy (e.g. `tuppy` or `tuprolog`), uninstall them via ```bash pip uninstall tuppy tuprolog ``` @@ -44,28 +44,7 @@ other aimed at (de)serialising terms theories, namely `tuprolog.theory.serializ ```bash python3 -m pip uninstall tuppy tuprolog ``` - -### How to develop 2PPy - -5. Restore Python dependencies via PIP, by running: - ```bash - pip install -r requirements.txt - ``` - On __Mac OS__ this may not work as expected. - Consider running the following command instead: - ```bash - python3 -m pip -r requirements.txt - ``` - -6. Restore JVM dependencies via `download-jars.sh`, by running: - ```bash - ./download-jars.sh - ``` - Notice that this command requires `curl` and `wget` to be installed on your system (`wget` may be lacking on __Mac OS__ and Windows) - -### How to use 2PPy as a library - -5. Install 2PPy from Pypi by running: +1. Install 2PPy from Pypi by running: ```bash pip install 2ppy ``` @@ -74,28 +53,27 @@ other aimed at (de)serialising terms theories, namely `tuprolog.theory.serializ ```bash python3 -m pip install 2ppy ``` - -6. Import `tuprolog.*` modules in your Python scripts - -7. Profit +1. Import `tuprolog.*` modules in your Python scripts +1. *Note for the expert users:* 2ppy downloads its own [Java Virtual Machine](https://en.wikipedia.org/wiki/Java_virtual_machine) in order to call Java bytecode from python. If you install the package with sdist, it's downloaded during install. If you use the binary wheels packaging, it's download on first import of the `tuprolog` package. -### How to use 2PPy as an executable +### How to develop 2PPy -5. Install 2PPy from Pypi by running: +1. Restore Python dev dependencies via PIP, by running: ```bash - pip install 2ppy + pip install -r requirements.txt ``` On __Mac OS__ this may not work as expected. Consider running the following command instead: ```bash - python3 -m pip install 2ppy + python3 -m pip -r requirements.txt ``` - -6. Run `tuprolog` module via - ```bash - python -m tuprolog - ``` +1. Write the code inside `tuprolog` and the unit tests inside `test` +1. Execute tests with `python -m pytest -p no:faulthandler` +1. Build the package with `python -m build` +1. Install the package locally with `python setup.py install` +1. Print the package version, computed from git tags with `python -m setuptools_git_versioning` -For the moment, running 2PPy means starting an interactive Python shell with pre-loaded `tuprolog.*` modules. +### How to use 2PPy as an executable -Eventually `python -m tuprolog` will launch a command-line logic solver. +1. Python shell mode: WIP +1. Logic solver [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop): WIP From a0fd4df4ce3f43ca4eb1c2073abe6a0088417b14 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Apr 2023 01:19:35 +0000 Subject: [PATCH 094/154] Bump pytest from 7.2.2 to 7.3.1 Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.2.2 to 7.3.1. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/7.2.2...7.3.1) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index b9e2ff1..967d7bc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # CI & Test dependencies flake8==6.0.0 -pytest==7.2.2 +pytest==7.3.1 setuptools-git-versioning==1.13.3 install-jdk==1.0.4 From 20b77a0ae1a368d731a368f9ca4fc957ea3e1afc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Apr 2023 01:07:56 +0000 Subject: [PATCH 095/154] Bump kotlin-bom from 1.8.10 to 1.8.21 Bumps [kotlin-bom](https://github.com/JetBrains/kotlin) from 1.8.10 to 1.8.21. - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/compare/v1.8.10...v1.8.21) --- updated-dependencies: - dependency-name: org.jetbrains.kotlin:kotlin-bom dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 473c314..9a90233 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ org.jetbrains.kotlin kotlin-bom - 1.8.10 + 1.8.21 From 17227898801fdfee6dc8a265319bcfdd20b75761 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 30 May 2023 13:54:22 +0200 Subject: [PATCH 096/154] Fix test warning --- test/solve/problog/test_problog_example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/solve/problog/test_problog_example.py b/test/solve/problog/test_problog_example.py index 1794543..e288d1f 100644 --- a/test/solve/problog/test_problog_example.py +++ b/test/solve/problog/test_problog_example.py @@ -33,7 +33,7 @@ def test_problog(self): if solution.is_yes: self.print(f"yes: {solution.solved_query} with probability {probability(solution)}") - self.assertEquals( + self.assertEqual( self.prints, [ 'yes: path(1, 2) with probability 0.6', From d0a899aebccec25cc1dfc46154a79d9504fe5868 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jul 2023 00:55:54 +0000 Subject: [PATCH 097/154] Bump install-jdk from 1.0.4 to 1.1.0 Bumps [install-jdk](https://github.com/jyksnw/install-jdk) from 1.0.4 to 1.1.0. - [Release notes](https://github.com/jyksnw/install-jdk/releases) - [Commits](https://github.com/jyksnw/install-jdk/compare/v1.0.4...v1.1.0) --- updated-dependencies: - dependency-name: install-jdk dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pyproject.toml | 4 ++-- requirements.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a259df2..b13b2c8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools>=61", "wheel", "setuptools-git-versioning<2", "install-jdk==1.0.4"] +requires = ["setuptools>=61", "wheel", "setuptools-git-versioning<2", "install-jdk==1.1.0"] build-backend = "setuptools.build_meta" [tool.setuptools-git-versioning] @@ -32,7 +32,7 @@ license = {file = "LICENSE"} keywords = ["prolog", "symbolic ai", "ecosystem", "tuprolog", "2p", "python"] dependencies = [ "JPype1==1.4.1", - "install-jdk==1.0.4" + "install-jdk==1.1.0" ] [project.urls] diff --git a/requirements.txt b/requirements.txt index 967d7bc..1eb56bc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,4 @@ flake8==6.0.0 pytest==7.3.1 setuptools-git-versioning==1.13.3 -install-jdk==1.0.4 +install-jdk==1.1.0 From a08c139d0dda247d8907ff765dc5efe6b9fb858d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Jul 2023 00:56:59 +0000 Subject: [PATCH 098/154] Bump flake8 from 6.0.0 to 6.1.0 Bumps [flake8](https://github.com/pycqa/flake8) from 6.0.0 to 6.1.0. - [Commits](https://github.com/pycqa/flake8/compare/6.0.0...6.1.0) --- updated-dependencies: - dependency-name: flake8 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 967d7bc..2d8c62b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # CI & Test dependencies -flake8==6.0.0 +flake8==6.1.0 pytest==7.3.1 setuptools-git-versioning==1.13.3 install-jdk==1.0.4 From 4b1bb665316e15e3d6c42492aa161e8490200ef0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Aug 2023 00:47:49 +0000 Subject: [PATCH 099/154] Bump org.jetbrains.kotlin:kotlin-bom from 1.8.21 to 1.9.10 Bumps [org.jetbrains.kotlin:kotlin-bom](https://github.com/JetBrains/kotlin) from 1.8.21 to 1.9.10. - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/v1.9.10/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/compare/v1.8.21...v1.9.10) --- updated-dependencies: - dependency-name: org.jetbrains.kotlin:kotlin-bom dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9a90233..9ceb0cb 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ org.jetbrains.kotlin kotlin-bom - 1.8.21 + 1.9.10 From 98af59e1a8dcad1523290378c23a20e92ba8bc19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 07:01:43 +0000 Subject: [PATCH 100/154] Bump pytest from 7.3.1 to 7.4.2 Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.3.1 to 7.4.2. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/7.3.1...7.4.2) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index b7f33de..4cdac1a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # CI & Test dependencies flake8==6.1.0 -pytest==7.3.1 +pytest==7.4.2 setuptools-git-versioning==1.13.3 install-jdk==1.1.0 From 73f388ff49f7e3d438b86d133a049d011ab3de5b Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 30 May 2023 14:04:03 +0200 Subject: [PATCH 101/154] Rename job --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4bbdbcc..b4cd7aa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,7 @@ defaults: jobs: build: + name: build & test strategy: matrix: os: [ubuntu, windows, macos] From d52098eb66cb07586dac80660aa411753f9c1cd0 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 30 May 2023 14:04:12 +0200 Subject: [PATCH 102/154] Add explanation comment --- tuprolog/libs/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tuprolog/libs/__init__.py b/tuprolog/libs/__init__.py index 0c93c7f..2c1f5c4 100644 --- a/tuprolog/libs/__init__.py +++ b/tuprolog/libs/__init__.py @@ -11,6 +11,6 @@ def install_java_if_missing() -> Path: return java_version = os.getenv('JAVA_VERSION', '11') destination_folder = str(CLASSPATH) - installation_path = Path(jdk.install(java_version, jre=not java_version.startswith('16'), path=destination_folder)) + installation_path = Path(jdk.install(java_version, jre=not java_version.startswith('16'), path=destination_folder)) # Java 16 doesn't have a JRE destination_folder = JAVA_HOME installation_path = installation_path.rename(destination_folder) From 771d303a171588cb39dde41ca1a308816f7249be Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 2 Oct 2023 09:37:35 +0200 Subject: [PATCH 103/154] Update 2p-Kt version. Fixes #3 --- pom.xml | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/pom.xml b/pom.xml index 9ceb0cb..a70e6c1 100644 --- a/pom.xml +++ b/pom.xml @@ -13,24 +13,12 @@ it.unibo.tuprolog repl-jvm - 0.31.1-dev02+0cd8a1ae6 - - - org.jetbrains.kotlin - kotlin-bom - - + 0.31.15 it.unibo.tuprolog solve-problog-jvm - 0.31.1-dev02+0cd8a1ae6 - - - org.jetbrains.kotlin - kotlin-bom - - + 0.31.15 From ea5961595c1894ca43f865b51eaedbf79b97f667 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 2 Oct 2023 09:37:41 +0200 Subject: [PATCH 104/154] Add flake8 rules --- .flake8 | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .flake8 diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..80676bc --- /dev/null +++ b/.flake8 @@ -0,0 +1,2 @@ +[flake8] +per-file-ignores = __init__.py:F401 From 2f4deaddeb9544130247e76b602c68d7ab350d96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 08:03:53 +0000 Subject: [PATCH 105/154] Bump setuptools-git-versioning from 1.13.3 to 1.13.5 Bumps [setuptools-git-versioning](https://github.com/dolfinus/setuptools-git-versioning) from 1.13.3 to 1.13.5. - [Release notes](https://github.com/dolfinus/setuptools-git-versioning/releases) - [Changelog](https://github.com/dolfinus/setuptools-git-versioning/blob/master/CHANGELOG.rst) - [Commits](https://github.com/dolfinus/setuptools-git-versioning/compare/v1.13.3...v1.13.5) --- updated-dependencies: - dependency-name: setuptools-git-versioning dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 4cdac1a..e023717 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # CI & Test dependencies flake8==6.1.0 pytest==7.4.2 -setuptools-git-versioning==1.13.3 +setuptools-git-versioning==1.13.5 install-jdk==1.1.0 From 8f03b08d69cfeb433104267e8d4536152066039d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 08:50:51 +0000 Subject: [PATCH 106/154] Bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b4cd7aa..f888e4f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: artifact-name: ${{ steps.artifact.outputs.artifact-name }} version: ${{ steps.artifact.outputs.version }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Python ${{ matrix.python-version }} @@ -93,7 +93,7 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install dependencies run: | python -m pip install --upgrade pip From 99a1f72329bd9dbfc066976870fb7cbd883e2ea2 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 2 Oct 2023 10:31:48 +0200 Subject: [PATCH 107/154] Add flake configuration file --- .flake8 | 5 ++++- .github/workflows/ci.yml | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.flake8 b/.flake8 index 80676bc..9866967 100644 --- a/.flake8 +++ b/.flake8 @@ -1,2 +1,5 @@ [flake8] -per-file-ignores = __init__.py:F401 +per-file-ignores = + __init__.py:F401, E402 + __main__.py:F401, F403 +max-line-length = 127 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f888e4f..b40916c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,7 +104,7 @@ jobs: # stop the build if there are Python syntax errors or undefined names python -m flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - python -m flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + python -m flake8 . --count --exit-zero --statistics install: strategy: From 4f2bb5d8117f252418d887e781b1e75f2a5dc98c Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 3 Oct 2023 01:27:36 +0200 Subject: [PATCH 108/154] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7bf28e0..7b6fe1c 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ other aimed at (de)serialising terms theories, namely `tuprolog.theory.serializ python3 -m pip install 2ppy ``` 1. Import `tuprolog.*` modules in your Python scripts -1. *Note for the expert users:* 2ppy downloads its own [Java Virtual Machine](https://en.wikipedia.org/wiki/Java_virtual_machine) in order to call Java bytecode from python. If you install the package with sdist, it's downloaded during install. If you use the binary wheels packaging, it's download on first import of the `tuprolog` package. +1. *Note for the expert users:* 2ppy downloads its own [Java Virtual Machine](https://en.wikipedia.org/wiki/Java_virtual_machine) in order to call Java bytecode from python. If you install the package with sdist, it's downloaded during install. If you use the binary wheels packaging, it's downloaded on first import of the `tuprolog` package. ### How to develop 2PPy From b51241725f008dbcdd7403a8a52cce5d7dd658c9 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Tue, 3 Oct 2023 01:27:59 +0200 Subject: [PATCH 109/154] Start Pythonic re-implementation --- test/core/operators/__init__.py | 0 test/core/{operators => }/test_operators.py | 5 +- test/core/test_parsing.py | 1 + test/core/test_scope.py | 5 +- test/core/test_substitution.py | 10 ++ test/core/test_terms.py | 22 ++-- test/core/test_try_except.py | 34 ++++++ tuprolog/core/__init__.py | 6 +- tuprolog/core/_ktadapt.py | 127 -------------------- tuprolog/core/_ktmath.py | 8 +- tuprolog/core/exception.py | 12 ++ tuprolog/core/exception/__init__.py | 15 --- tuprolog/core/exception/_ktadapt.py | 25 ---- tuprolog/core/operators/__init__.py | 7 +- tuprolog/core/operators/_ktadapt.py | 18 --- tuprolog/core/parsing/__init__.py | 10 +- tuprolog/jvmutils.py | 87 ++++++++++---- tuprolog/solve/prolog/__init__.py | 6 +- 18 files changed, 147 insertions(+), 251 deletions(-) delete mode 100644 test/core/operators/__init__.py rename test/core/{operators => }/test_operators.py (98%) create mode 100644 test/core/test_parsing.py create mode 100644 test/core/test_substitution.py create mode 100644 test/core/test_try_except.py create mode 100644 tuprolog/core/exception.py delete mode 100644 tuprolog/core/exception/__init__.py delete mode 100644 tuprolog/core/exception/_ktadapt.py diff --git a/test/core/operators/__init__.py b/test/core/operators/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/test/core/operators/test_operators.py b/test/core/test_operators.py similarity index 98% rename from test/core/operators/test_operators.py rename to test/core/test_operators.py index 40ba9f5..a25d781 100644 --- a/test/core/operators/test_operators.py +++ b/test/core/test_operators.py @@ -1,13 +1,10 @@ import random import string import unittest - from tuprolog.core import * from tuprolog.core.operators import DEFAULT_OPERATORS, EMPTY_OPERATORS, STANDARD_OPERATORS, XF, XFY, YF, YFX, FX, FY, \ XFX, operator, operator_set, OperatorSet, specifier - -# noinspection PyUnresolvedReferences -from java.lang import IllegalArgumentException +from java.lang import IllegalArgumentException # type: ignore class AbstractTestOperatorStuff(unittest.TestCase): diff --git a/test/core/test_parsing.py b/test/core/test_parsing.py new file mode 100644 index 0000000..a5fe001 --- /dev/null +++ b/test/core/test_parsing.py @@ -0,0 +1 @@ +# TODO: write tests \ No newline at end of file diff --git a/test/core/test_scope.py b/test/core/test_scope.py index 690b3eb..93cb24c 100644 --- a/test/core/test_scope.py +++ b/test/core/test_scope.py @@ -1,5 +1,5 @@ import unittest -from tuprolog.core import scope, var, Scope, variables, struct +from tuprolog.core import scope, var, Scope, variables, struct, FAIL class TestScope(unittest.TestCase): @@ -26,6 +26,9 @@ def test_variables_reuse(self): fAB = s.struct('f', s.var('A'), s.var('B')) self.assertEqual(struct('f', A, B), fAB) + def test_attributes(self): + s = scope() + self.assertEqual(s.fail, FAIL) if __name__ == '__main__': unittest.main() diff --git a/test/core/test_substitution.py b/test/core/test_substitution.py new file mode 100644 index 0000000..931df38 --- /dev/null +++ b/test/core/test_substitution.py @@ -0,0 +1,10 @@ +import unittest +from tuprolog.core import substitution, var, struct, FAIL + + +class TestSubstitution(unittest.TestCase): + + def test_substitution_creation(self): + sub = substitution({}) + self.assertEqual(0, len(sub)) + self.assertEqual(True, sub.is_success) diff --git a/test/core/test_terms.py b/test/core/test_terms.py index f0e1bc1..d16be52 100644 --- a/test/core/test_terms.py +++ b/test/core/test_terms.py @@ -15,19 +15,21 @@ def setUp(self): self.struct = struct('f', self.atom, self.integer, self.real) self.struct2 = struct('f', [self.atom, self.integer, self.real]) - def test_simple_terms_creation(self): - self.assertEqual(self.atom.getValue(), 'a') - self.assertEqual(self.integer.getValue().toInt(), 1) - self.assertEqual(self.real.getValue().toDouble(), 1.2) - self.assertEqual(self.var.getName(), 'X') - self.assertEqual(self.true.getValue(), 'true') - self.assertEqual(self.false.getValue(), 'false') - self.assertEqual(self.fail.getValue(), 'fail') + self.assertEqual(self.atom.value, 'a') + self.assertEqual(self.integer.value.toInt(), 1) + self.assertEqual(self.real.value.toDouble(), 1.2) + self.assertEqual(self.var.name, 'X') + self.assertEqual(self.true.value, 'true') + self.assertEqual(self.false.value, 'false') + self.assertEqual(self.fail.value, 'fail') + self.assertEqual(list(self.var.getVariables())[0], self.var) # TODO: make pythonic + self.assertEqual(True, self.var.structurally_equals(var('Y'))) + self.assertEqual(True, self.true.isTruth()) # TODO: make pythonic def test_struct_creation(self): - self.assertEqual(self.struct.getFunctor(), 'f') - self.assertEqual(self.struct.getArity(), 3) + self.assertEqual(self.struct.functor, 'f') + self.assertEqual(self.struct.arity, 3) self.assertEqual(self.struct.getArgAt(0), self.atom) self.assertEqual(self.struct.getArgAt(1), self.integer) self.assertEqual(self.struct.getArgAt(2), self.real) diff --git a/test/core/test_try_except.py b/test/core/test_try_except.py new file mode 100644 index 0000000..4e7d48a --- /dev/null +++ b/test/core/test_try_except.py @@ -0,0 +1,34 @@ +import unittest +from tuprolog.core.exception import * +from tuprolog.core import Substitution, Atom + + +class TestExceptions(unittest.TestCase): + + def test_TuprologException(self): + try: + raise TuPrologException("test") + except TuPrologException as e: + self.assertEqual("test", e.message) + + def test_SubstitutionException(self): + sub = Substitution.empty() + try: + raise SubstitutionException(sub, "test") + except SubstitutionException as e: + self.assertEqual("test", e.message) + self.assertEqual(sub, e.substitution) + + def test_SubstitutionApplicationException(self): + term = Atom.of("test") + sub = Substitution.empty() + try: + raise SubstitutionApplicationException(term, sub, "test") + except SubstitutionApplicationException as e: + self.assertEqual("test", e.message) + self.assertEqual(sub, e.substitution) + self.assertEqual(term, e.term) + + +if __name__ == '__main__': + unittest.main() diff --git a/tuprolog/core/__init__.py b/tuprolog/core/__init__.py index ef9f942..bf78a85 100644 --- a/tuprolog/core/__init__.py +++ b/tuprolog/core/__init__.py @@ -1,11 +1,9 @@ from decimal import Decimal - from tuprolog import logger +from ._ktadapt import * import jpype import jpype.imports -from ._ktadapt import * -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.core as _core +import it.unibo.tuprolog.core as _core # type: ignore from tuprolog.pyutils import iterable_or_varargs from tuprolog.jvmutils import jiterable, jmap from typing import Iterable, Dict, Tuple as PyTuple diff --git a/tuprolog/core/_ktadapt.py b/tuprolog/core/_ktadapt.py index 95e12fa..640df6d 100644 --- a/tuprolog/core/_ktadapt.py +++ b/tuprolog/core/_ktadapt.py @@ -18,105 +18,10 @@ def __jclass_init__(cls): def __getitem__(self, item, *items): return self.get(item, *items) - @property - def variables(self): - return self.getVariables() - - def structurally_equals(self, other): - return self.structurallyEquals(other) - @jpype.JOverride() def equals(self, other, use_var_complete_name: bool = True): return self.equals_(other, use_var_complete_name) - @property - def is_var(self): - return self.isVar() - - @property - def is_ground(self): - return self.isGround() - - @property - def is_struct(self): - return self.isStruct() - - @property - def is_truth(self): - return self.isTruth() - - @property - def is_recursive(self): - return self.isRecursive() - - @property - def is_atom(self): - return self.isAtom() - - @property - def is_constant(self): - return self.isConstant() - - @property - def is_number(self): - return self.isNumber() - - @property - def is_integer(self): - return self.isInteger() - - @property - def is_real(self): - return self.isReal() - - @property - def is_list(self): - return self.isList() - - @property - def is_tuple(self): - return self.isTuple() - - @property - def is_block(self): - return self.isBlock() - - @property - def is_clause(self): - return self.isClause() - - @property - def is_rule(self): - return self.isRule() - - @property - def is_fact(self): - return self.isFact() - - @property - def is_directive(self): - return self.isDirective() - - @property - def is_cons(self): - return self.isCons() - - @property - def is_empty_list(self): - return self.isEmptyList() - - @property - def is_true(self): - return self.isTrue() - - @property - def is_fail(self): - return self.isFail() - - @property - def is_indicator(self): - return self.isIndicator() - def fresh_copy(self, scope=None): if scope is None: return self.freshCopy() @@ -419,14 +324,6 @@ class _KtSubstitution: def __jclass_init__(cls): pass - @property - def is_success(self): - return self.isSuccess() - - @property - def is_failed(self): - return self.isFailed() - def apply_to(self, term): return self.applyTo(term) @@ -461,22 +358,6 @@ def __contains__(self, item): def __getitem__(self, item): return self.get(item) - @property - def variables(self): - return self.getVariables() - - @property - def fail(self): - return self.getFail() - - @property - def empty_list(self): - return self.getEmptyList() - - @property - def empty_block(self): - return self.getEmptyBlock() - def atom(self, string): return self.atomOf(string) @@ -535,13 +416,5 @@ def list_from(self, items, last=None): def tuple(self, first, second, *others): return iterable_or_varargs(others, lambda os: self.tupleOf(jiterable([first, second] + list(os)))) - @property - def anonymous(self): - return self.getAnonymous() - - @property - def whatever(self): - return self.getWhatever() - logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.core.*") diff --git a/tuprolog/core/_ktmath.py b/tuprolog/core/_ktmath.py index c225b23..a2b195c 100644 --- a/tuprolog/core/_ktmath.py +++ b/tuprolog/core/_ktmath.py @@ -1,12 +1,8 @@ -# noinspection PyUnresolvedReferences from typing import Union import decimal import jpype.imports -# noinspection PyUnresolvedReferences -import org.gciatto.kt.math as _ktmath -# noinspection PyUnresolvedReferences -import java.lang as _java_lang -from math import ceil +import org.gciatto.kt.math as _ktmath # type: ignore +import java.lang as _java_lang # type: ignore from tuprolog.pyutils import and_then diff --git a/tuprolog/core/exception.py b/tuprolog/core/exception.py new file mode 100644 index 0000000..a17de69 --- /dev/null +++ b/tuprolog/core/exception.py @@ -0,0 +1,12 @@ +from tuprolog import logger +import jpype.imports +import it.unibo.tuprolog.core.exception as _exceptions # type: ignore + +TuPrologException = _exceptions.TuPrologException + +SubstitutionException = _exceptions.SubstitutionException + +SubstitutionApplicationException = _exceptions.SubstitutionApplicationException + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.core.exception.*") diff --git a/tuprolog/core/exception/__init__.py b/tuprolog/core/exception/__init__.py deleted file mode 100644 index 65d044a..0000000 --- a/tuprolog/core/exception/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.core.exception as _exceptions -from ._ktadapt import * - -TuPrologException = _exceptions.TuPrologException - -SubstitutionException = _exceptions.TuPrologException - -SubstitutionApplicationException = _exceptions.TuPrologException - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.core.exception.*") diff --git a/tuprolog/core/exception/_ktadapt.py b/tuprolog/core/exception/_ktadapt.py deleted file mode 100644 index c43369a..0000000 --- a/tuprolog/core/exception/_ktadapt.py +++ /dev/null @@ -1,25 +0,0 @@ -from tuprolog import logger -import jpype - - -@jpype.JImplementationFor("it.unibo.tuprolog.core.exception.SubstitutionException") -class _KtSubstitutionException: - def __jclass_init__(cls): - pass - - @property - def substitution(self): - return self.getSubstitution() - - -@jpype.JImplementationFor("it.unibo.tuprolog.core.exception.SubstitutionApplicationException") -class _KtSubstitutionApplicationException: - def __jclass_init__(cls): - pass - - @property - def term(self): - return self.getTerm() - - -logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.core.exception.*") diff --git a/tuprolog/core/operators/__init__.py b/tuprolog/core/operators/__init__.py index 695db49..96119fe 100644 --- a/tuprolog/core/operators/__init__.py +++ b/tuprolog/core/operators/__init__.py @@ -1,17 +1,12 @@ from tuprolog import logger from ._ktadapt import * -# noinspection PyUnresolvedReferences -import jpype -# noinspection PyUnresolvedReferences import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.core.operators as _operators +import it.unibo.tuprolog.core.operators as _operators # type: ignore from tuprolog.jvmutils import jiterable from tuprolog.pyutils import iterable_or_varargs from tuprolog.core import Atom, Integer, Struct, Term from functools import singledispatch - Operator = _operators.Operator OperatorSet = _operators.OperatorSet diff --git a/tuprolog/core/operators/_ktadapt.py b/tuprolog/core/operators/_ktadapt.py index 14edd32..7a9a557 100644 --- a/tuprolog/core/operators/_ktadapt.py +++ b/tuprolog/core/operators/_ktadapt.py @@ -2,24 +2,6 @@ import jpype -@jpype.JImplementationFor("it.unibo.tuprolog.core.operators.Operator") -class _KtOperator: - def __jclass_init__(cls): - pass - - @property - def functor(self): - return self.getFunctor() - - @property - def specifier(self): - return self.getSpecifier() - - @property - def priority(self): - return self.getPriority() - - @jpype.JImplementationFor("it.unibo.tuprolog.core.operators.OperatorSet") class _KtOperatorSet: def __jclass_init__(cls): diff --git a/tuprolog/core/parsing/__init__.py b/tuprolog/core/parsing/__init__.py index 4f0cfe5..6901b8e 100644 --- a/tuprolog/core/parsing/__init__.py +++ b/tuprolog/core/parsing/__init__.py @@ -1,13 +1,11 @@ +from typing import Union, Iterable from tuprolog import logger -# noinspection PyUnresolvedReferences +from ._ktadapt import * import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.core.parsing as _parsing -from tuprolog.core import Term, Struct, Constant, Var, Atom, Numeric, Integer, Real, Clause +import it.unibo.tuprolog.core.parsing as _parsing # type: ignore from tuprolog.jvmutils import InputStream +from tuprolog.core import Term, Struct, Constant, Var, Atom, Numeric, Integer, Real, Clause from tuprolog.core.operators import OperatorSet, DEFAULT_OPERATORS -from typing import Union, Iterable -from ._ktadapt import * TermParser = _parsing.TermParser diff --git a/tuprolog/jvmutils.py b/tuprolog/jvmutils.py index c98c344..141646b 100644 --- a/tuprolog/jvmutils.py +++ b/tuprolog/jvmutils.py @@ -1,24 +1,17 @@ +from typing import Iterable as PyIterable +from typing import Iterator as PyIterator +from typing import Mapping, MutableMapping, Callable, Any from tuprolog import logger -# noinspection PyUnresolvedReferences import jpype -# noinspection PyUnresolvedReferences import jpype.imports -# noinspection PyProtectedMember -from _jpype import _JObject as JObjectClass -# noinspection PyUnresolvedReferences -import java.util as _jutils -# noinspection PyUnresolvedReferences -import java.lang as _jlang -# noinspection PyUnresolvedReferences -import kotlin as _kotlin -# noinspection PyUnresolvedReferences -import kotlin.sequences as _ksequences -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.utils as _tuprolog_utils +import jpype.beans +from _jpype import _JObject as JObjectClass, _JMethod as JMethodClass # type: ignore +import java.util as _jutils # type: ignore +import java.lang as _jlang # type: ignore +import kotlin as _kotlin # type: ignore +import kotlin.sequences as _ksequences # type: ignore +import it.unibo.tuprolog.utils as _tuprolog_utils # type: ignore -from typing import Iterable as PyIterable -from typing import Iterator as PyIterator -from typing import Mapping, MutableMapping, Callable, Any from .jvmioutils import * @@ -213,6 +206,57 @@ def __ge__(self, other): return self.compareTo(other) >= 0 +def to_snake_case(camel_str: str) -> str: + return "".join("_" + x.lower() if x.isupper() and camel_str[i + 1:i + 2].islower() else x for i, x in enumerate(camel_str)).lstrip("_") + + +@jpype.JImplementationFor("java.lang.Object") +class _KtObjectWithSmartAccessors: + def __jclass_init__(self): + for name, member in self.__dict__.copy().items(): + if name.startswith("_"): + continue + if isinstance(member, JMethodClass) and len(name) > 3: + snake_case = to_snake_case(name) + if snake_case.startswith("get_") and member._isBeanAccessor(): + snake_case = snake_case[4:] + if snake_case not in self.__dict__: + self._customize(snake_case, property(member)) + elif snake_case not in self.__dict__: + self._customize(snake_case, member) + + # def __getattribute__(self, name: str) -> Any: + # """ + # This method will convert Python styled member access to kotlin styled member access, + # as a second attempt to access the correct member through JPype + # after the first attempt failed. + # """ + # try: + # return object.__getattribute__(self, name) + # except AttributeError: + # if name.startswith("_"): + # raise + # alias = to_camel_case(name) + # try: + # if alias == name: + # raise + # result = object.__getattribute__(self, alias) + # except AttributeError: + # special_prefixes = ["get", "set", "has", "is"] + # starts_with_special_prefix = None + # for prefix in special_prefixes: + # if alias.startswith(prefix) and not alias[len(prefix)].islower(): + # starts_with_special_prefix = prefix + # break + # if starts_with_special_prefix is not None: + # raise + # alias = f"get{name[0].upper()}{name[1:]}" + # result = object.__getattribute__(self, alias) + # if result._isBeanAccessor(): + # return result() + # return result + + @jpype.JImplementationFor("java.lang.Throwable") class _JvmThrowable: def __jclass_init__(self): @@ -222,14 +266,6 @@ def __jclass_init__(self): def message(self): return self.getMessage() - @property - def localized_message(self): - return self.getLocalizedMessage() - - @property - def cause(self): - return self.getCause() - class _KtFunction(Callable): def __init__(self, arity: int, function: Callable): @@ -261,5 +297,4 @@ def invoke(self, *args): _kt_function_classes[arity] = _KtFunctionN return _kt_function_classes[arity] - logger.debug("Configure JVM-specific extensions") diff --git a/tuprolog/solve/prolog/__init__.py b/tuprolog/solve/prolog/__init__.py index f7633e1..97636d7 100644 --- a/tuprolog/solve/prolog/__init__.py +++ b/tuprolog/solve/prolog/__init__.py @@ -1,16 +1,16 @@ from tuprolog import logger from tuprolog.solve.flags import DEFAULT_FLAG_STORE, FlagStore -from tuprolog.solve.library import libraries, Libraries +from tuprolog.solve.library import libraries, Library from tuprolog.solve.channel import InputChannel, OutputChannel, std_out, std_in, std_err, warn from tuprolog.theory import theory, mutable_theory, Theory from tuprolog.solve import Solver, SolverFactory -_PROLOG_SOLVER_FACTORY = Solver.getProlog() +_PROLOG_SOLVER_FACTORY = Solver.prolog() def prolog_solver( - libraries: Libraries = libraries(), + libraries: Library = libraries(), flags: FlagStore = DEFAULT_FLAG_STORE, static_kb: Theory = theory(), dynamic_kb: Theory = mutable_theory(), From 320be3eedb461d6f74ebefcc090aa7504fe097a1 Mon Sep 17 00:00:00 2001 From: Luca Deluigi Date: Tue, 3 Oct 2023 16:02:23 +0200 Subject: [PATCH 110/154] Improve installation script. Adding javadoc to jars --- setup.py | 23 ++++++++++++++++------- tuprolog/libs/__init__.py | 9 ++++++++- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/setup.py b/setup.py index 63746f4..8e2a3ab 100644 --- a/setup.py +++ b/setup.py @@ -17,17 +17,26 @@ def is_windows(): return platform.system() == 'Windows' -def download_jars(): - proc = subprocess.Popen(MAVEN_EXECUTABLE + ['-v'], shell=is_windows(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) +def run_maven(*args, cwd=None) -> (str, str): + proc = subprocess.Popen( + MAVEN_EXECUTABLE + list(args), + shell=is_windows(), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + cwd=cwd) stdout, stderr = proc.communicate() if proc.returncode != 0: - raise RuntimeError(f'Could not run mvn:\n{stdout}\n{stderr}') + raise RuntimeError(f'Error while running mvn:\n{stdout}\n{stderr}') + return stdout, stderr + + +def download_jars(): + stdout, _ = run_maven('-v') if 'Apache Maven' not in stdout: raise RuntimeError(f'Could not find Apache Maven in {stdout}') - proc = subprocess.Popen(MAVEN_EXECUTABLE + ['dependency:copy-dependencies', f'-DoutputDirectory={JAR_FOLDER}'], shell=is_windows(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd=Path(__file__).parent) - stdout, stderr = proc.communicate() - if proc.returncode != 0: - raise RuntimeError(f'Error while downloading JARs:\n{stdout}\n{stderr}') + run_maven('dependency:copy-dependencies', f'-DoutputDirectory={JAR_FOLDER}', cwd=Path(__file__).parent) + run_maven('dependency:copy-dependencies', f'-DoutputDirectory={JAR_FOLDER}', '-Dclassifier=javadoc', cwd=Path(__file__).parent) class BuildPyCommand(build_py): diff --git a/tuprolog/libs/__init__.py b/tuprolog/libs/__init__.py index 2c1f5c4..3ebd2fc 100644 --- a/tuprolog/libs/__init__.py +++ b/tuprolog/libs/__init__.py @@ -1,16 +1,23 @@ import os import jdk +import shutil +import logging from pathlib import Path JAVA_HOME = Path(__file__).parent / 'java' CLASSPATH = Path(__file__).parent +logger = logging.getLogger('tuprolog') + def install_java_if_missing() -> Path: if JAVA_HOME.exists(): return java_version = os.getenv('JAVA_VERSION', '11') destination_folder = str(CLASSPATH) + logger.info(f'Downloading Java {java_version} in {destination_folder}') installation_path = Path(jdk.install(java_version, jre=not java_version.startswith('16'), path=destination_folder)) # Java 16 doesn't have a JRE destination_folder = JAVA_HOME - installation_path = installation_path.rename(destination_folder) + logger.info(f'Installing Java {java_version} in {destination_folder}') + shutil.copytree(installation_path, destination_folder, dirs_exist_ok=True) + shutil.rmtree(installation_path, ignore_errors=True) From b7cb5191aab2eb63acf99df5ffc30c58ce01e94b Mon Sep 17 00:00:00 2001 From: Luca Deluigi Date: Wed, 4 Oct 2023 01:38:08 +0200 Subject: [PATCH 111/154] Remove javadoc (not working for now) --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 8e2a3ab..ee06421 100644 --- a/setup.py +++ b/setup.py @@ -36,7 +36,7 @@ def download_jars(): if 'Apache Maven' not in stdout: raise RuntimeError(f'Could not find Apache Maven in {stdout}') run_maven('dependency:copy-dependencies', f'-DoutputDirectory={JAR_FOLDER}', cwd=Path(__file__).parent) - run_maven('dependency:copy-dependencies', f'-DoutputDirectory={JAR_FOLDER}', '-Dclassifier=javadoc', cwd=Path(__file__).parent) + # run_maven('dependency:copy-dependencies', f'-DoutputDirectory={JAR_FOLDER}', '-Dclassifier=javadoc', cwd=Path(__file__).parent) class BuildPyCommand(build_py): From 368342c388477ec4940199ff54d1d46e5d902746 Mon Sep 17 00:00:00 2001 From: Luca Deluigi Date: Wed, 4 Oct 2023 01:38:32 +0200 Subject: [PATCH 112/154] Fix _KtObjectWithSmartPythonicAccessors and add tests --- test/core/test_substitution.py | 1 + test/core/test_terms.py | 11 ++++-- tuprolog/jvmutils.py | 68 +++++++++++++--------------------- 3 files changed, 34 insertions(+), 46 deletions(-) diff --git a/test/core/test_substitution.py b/test/core/test_substitution.py index 931df38..86ad117 100644 --- a/test/core/test_substitution.py +++ b/test/core/test_substitution.py @@ -7,4 +7,5 @@ class TestSubstitution(unittest.TestCase): def test_substitution_creation(self): sub = substitution({}) self.assertEqual(0, len(sub)) + self.assertEqual(True, sub.isSuccess()) self.assertEqual(True, sub.is_success) diff --git a/test/core/test_terms.py b/test/core/test_terms.py index d16be52..764a3f3 100644 --- a/test/core/test_terms.py +++ b/test/core/test_terms.py @@ -9,8 +9,8 @@ def setUp(self): self.integer = integer(1) self.real = real(1.2) self.var = var("X") - self.true = truth(True) - self.false = truth(False) + self.true = TRUE + self.false = FALSE self.fail = FAIL self.struct = struct('f', self.atom, self.integer, self.real) self.struct2 = struct('f', [self.atom, self.integer, self.real]) @@ -23,9 +23,12 @@ def test_simple_terms_creation(self): self.assertEqual(self.true.value, 'true') self.assertEqual(self.false.value, 'false') self.assertEqual(self.fail.value, 'fail') - self.assertEqual(list(self.var.getVariables())[0], self.var) # TODO: make pythonic + self.assertEqual(True, self.false.isTruth()) + self.assertEqual(True, self.true.isTruth()) + self.assertEqual(list(self.var.variables)[0], self.var) self.assertEqual(True, self.var.structurally_equals(var('Y'))) - self.assertEqual(True, self.true.isTruth()) # TODO: make pythonic + self.assertEqual(True, self.false.is_truth) + self.assertEqual(True, self.true.is_truth) def test_struct_creation(self): self.assertEqual(self.struct.functor, 'f') diff --git a/tuprolog/jvmutils.py b/tuprolog/jvmutils.py index 141646b..a45a2dc 100644 --- a/tuprolog/jvmutils.py +++ b/tuprolog/jvmutils.py @@ -211,50 +211,34 @@ def to_snake_case(camel_str: str) -> str: @jpype.JImplementationFor("java.lang.Object") -class _KtObjectWithSmartAccessors: +class _KtObjectWithSmartPythonicAccessors: def __jclass_init__(self): - for name, member in self.__dict__.copy().items(): - if name.startswith("_"): + members = dir(self) + members_set = set(members) + for name in members: + member = getattr(self, name, None) + if member is None: continue - if isinstance(member, JMethodClass) and len(name) > 3: - snake_case = to_snake_case(name) - if snake_case.startswith("get_") and member._isBeanAccessor(): - snake_case = snake_case[4:] - if snake_case not in self.__dict__: - self._customize(snake_case, property(member)) - elif snake_case not in self.__dict__: - self._customize(snake_case, member) - - # def __getattribute__(self, name: str) -> Any: - # """ - # This method will convert Python styled member access to kotlin styled member access, - # as a second attempt to access the correct member through JPype - # after the first attempt failed. - # """ - # try: - # return object.__getattribute__(self, name) - # except AttributeError: - # if name.startswith("_"): - # raise - # alias = to_camel_case(name) - # try: - # if alias == name: - # raise - # result = object.__getattribute__(self, alias) - # except AttributeError: - # special_prefixes = ["get", "set", "has", "is"] - # starts_with_special_prefix = None - # for prefix in special_prefixes: - # if alias.startswith(prefix) and not alias[len(prefix)].islower(): - # starts_with_special_prefix = prefix - # break - # if starts_with_special_prefix is not None: - # raise - # alias = f"get{name[0].upper()}{name[1:]}" - # result = object.__getattribute__(self, alias) - # if result._isBeanAccessor(): - # return result() - # return result + elif name.startswith("_") or '$' in name: + continue + elif isinstance(member, JMethodClass): + if len(name) > 3: + snake_case = to_snake_case(name) + method_has_0_args = member.__annotations__.keys() == {"return"} + method_is_property = False + # Shorten method name and promote to property if it's a getter + if method_has_0_args and snake_case.startswith("get_"): + snake_case = snake_case[4:] + method_is_property = True + # Promote method to property if it's a boolean getter + elif method_has_0_args and snake_case.startswith("is_"): + method_is_property = True + if snake_case not in members_set or getattr(self, snake_case, None) is None: + self._customize(snake_case, property(member) if method_is_property else member) + members_set.add(snake_case) + else: + member = getattr(self, snake_case, None) + pass @jpype.JImplementationFor("java.lang.Throwable") From becf429784b250ef88ea28f528007a48ec894fa2 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 4 Oct 2023 12:30:58 +0200 Subject: [PATCH 113/154] Drop jpype.beans import and re-implement it to avoid clashes --- test/core/test_terms.py | 4 ++-- tuprolog/jvmutils.py | 36 ++++++++++++++++++++++++------------ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/test/core/test_terms.py b/test/core/test_terms.py index 764a3f3..53e5c63 100644 --- a/test/core/test_terms.py +++ b/test/core/test_terms.py @@ -17,8 +17,8 @@ def setUp(self): def test_simple_terms_creation(self): self.assertEqual(self.atom.value, 'a') - self.assertEqual(self.integer.value.toInt(), 1) - self.assertEqual(self.real.value.toDouble(), 1.2) + self.assertEqual(self.integer.value.to_int(), 1) + self.assertEqual(self.real.value.to_double(), 1.2) self.assertEqual(self.var.name, 'X') self.assertEqual(self.true.value, 'true') self.assertEqual(self.false.value, 'false') diff --git a/tuprolog/jvmutils.py b/tuprolog/jvmutils.py index a45a2dc..d7bcf13 100644 --- a/tuprolog/jvmutils.py +++ b/tuprolog/jvmutils.py @@ -4,7 +4,6 @@ from tuprolog import logger import jpype import jpype.imports -import jpype.beans from _jpype import _JObject as JObjectClass, _JMethod as JMethodClass # type: ignore import java.util as _jutils # type: ignore import java.lang as _jlang # type: ignore @@ -219,26 +218,39 @@ def __jclass_init__(self): member = getattr(self, name, None) if member is None: continue - elif name.startswith("_") or '$' in name: + elif name.startswith("_") or '$' in name or name == 'getClass': continue elif isinstance(member, JMethodClass): if len(name) > 3: snake_case = to_snake_case(name) method_has_0_args = member.__annotations__.keys() == {"return"} - method_is_property = False + add_property = None + add_method = (snake_case, member) # Shorten method name and promote to property if it's a getter if method_has_0_args and snake_case.startswith("get_"): - snake_case = snake_case[4:] - method_is_property = True + property_name = snake_case[4:] + if member._isBeanAccessor(): + getter = member + setter_name = "set" + name.removeprefix("get") + setter = getattr(self, setter_name, None) + if setter is not None and isinstance(setter, JMethodClass) and setter._isBeanMutator(): + add_property = (property_name, property(fget=getter, fset=setter)) + else: + add_property = (property_name, property(fget=getter)) + else: + add_property = (property_name, property(fget=member)) # Promote method to property if it's a boolean getter elif method_has_0_args and snake_case.startswith("is_"): - method_is_property = True - if snake_case not in members_set or getattr(self, snake_case, None) is None: - self._customize(snake_case, property(member) if method_is_property else member) - members_set.add(snake_case) - else: - member = getattr(self, snake_case, None) - pass + add_property = (snake_case, property(fget=member)) + # Do not add method with the same name + add_method = None + # Add method and property + for to_add in (add_property, add_method): + if to_add is not None: + # Avoid conflicts with existing members + if to_add[0] not in members_set or not hasattr(self, to_add[0]): + self._customize(*to_add) + members_set.add(to_add[0]) @jpype.JImplementationFor("java.lang.Throwable") From 67a1c7c7dc1c68c5f39c3351d7adf6d6feeb56cc Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 4 Oct 2023 16:46:51 +0200 Subject: [PATCH 114/154] Remove code that is not necessary anymore --- tuprolog/core/_ktadapt.py | 211 --------------------------- tuprolog/jvmutils.py | 1 + tuprolog/solve/_ktadapt.py | 131 ----------------- tuprolog/theory/_ktadapt.py | 36 ----- tuprolog/unify/__init__.py | 1 - tuprolog/unify/_ktadapt.py | 15 -- tuprolog/unify/exception/__init__.py | 1 - tuprolog/unify/exception/_ktadapt.py | 19 --- tuprolog/utils/__init__.py | 1 - tuprolog/utils/_ktadapt.py | 24 --- 10 files changed, 1 insertion(+), 439 deletions(-) delete mode 100644 tuprolog/unify/_ktadapt.py delete mode 100644 tuprolog/unify/exception/_ktadapt.py delete mode 100644 tuprolog/utils/_ktadapt.py diff --git a/tuprolog/core/_ktadapt.py b/tuprolog/core/_ktadapt.py index 640df6d..daf58c4 100644 --- a/tuprolog/core/_ktadapt.py +++ b/tuprolog/core/_ktadapt.py @@ -34,85 +34,13 @@ class _KtStruct: def __jclass_init__(cls): pass - @property - def functor(self): - return self.getFunctor() - - @property - def args(self): - return self.getArgs() - - @property - def argsSequence(self): - return self.getArgsSequence() - - @property - def arity(self): - return self.getArity() - - @property - def is_functor_well_formed(self): - return self.isFunctorWellFormed() - - @property - def indicator(self): - return self.getIndicator() - - def get_arg_at(self, index): - return self.getArgAt(index) - - def add_last(self, argument): - return self.addLast(argument) - - def add_first(self, argument): - return self.addFirst(argument) - def insert_at(self, index, argument): return self.addFirst(index, argument) - def set_functor(self, functor): - return self.setFunctor(functor) - def set_args(self, *args): return iterable_or_varargs(args, lambda xs: self.setArgs(jiterable(args))) -@jpype.JImplementationFor("it.unibo.tuprolog.core.Var") -class _KtVar: - def __jclass_init__(cls): - pass - - @property - def is_anonymous(self): - return self.isAnonymous() - - @property - def name(self): - return self.getName() - - @property - def id(self): - return self.getId() - - @property - def complete_name(self): - return self.getCompleteName() - - @property - def is_name_well_formed(self): - return self.isNameWellFormed() - - -@jpype.JImplementationFor("it.unibo.tuprolog.core.Constant") -class _KtConstant: - def __jclass_init__(cls): - pass - - @property - def value(self): - return self.getValue() - - @jpype.JImplementationFor("it.unibo.tuprolog.core.Numeric") class _KtNumeric: def __jclass_init__(cls): @@ -173,166 +101,27 @@ def __len__(self): def to_iterable(self): return self.toSequence() - def to_list(self): - return self.toList() - - def to_array(self): - return self.toArray() - - -@jpype.JImplementationFor("it.unibo.tuprolog.core.List") -class _KtList: - def __jclass_init__(cls): - pass - - @property - def is_well_formed(self): - return self.isWellFormed() - - @property - def last(self): - return self.getLast() - - def estimated_length(self): - return self.getEstimatedLength() - - -@jpype.JImplementationFor("it.unibo.tuprolog.core.Cons") -class _KtCons: - def __jclass_init__(cls): - pass - - @property - def head(self): - return self.getHead() - - @property - def tail(self): - return self.getTail() - - -@jpype.JImplementationFor("it.unibo.tuprolog.core.Tuple") -class _KtTuple: - def __jclass_init__(cls): - pass - - @property - def left(self): - return self.getLeft() - - @property - def right(self): - return self.getRight() - @jpype.JImplementationFor("it.unibo.tuprolog.core.Clause") class _KtClause: def __jclass_init__(cls): pass - @property - def head(self): - return self.getHead() - - @property - def body(self): - return self.getBody() - - @property - def is_well_formed(self): - return self.isWellFormed() - - @property - def body_items(self): - return self.getBodyItems() - - @property - def body_size(self): - return self.getBodySize() - - def get_body_item(self, index): - return self.getBodyItem(index) - - def set_head(self, head): - return self.setHead(head) - - def set_body(self, term): - return self.setBody(term) - - def set_head_functor(self, functor): - return self.setHeadFunctor(functor) - def set_head_args(self, *args): return iterable_or_varargs(args, lambda xs: self.setHeadArgs(jiterable(args))) def insert_head_arg(self, index, argument): return self.setHeadArg(index, argument) - def add_first_head_arg(self, argument): - return self.addFirstHeadArg(argument) - - def add_last_head_arg(self, argument): - return self.addLastHeadArg(argument) - - def append_head_arg(self, argument): - return self.appendHeadArg(argument) - def set_body_items(self, *args): return iterable_or_varargs(args, lambda xs: self.setBodyItems(jiterable(args))) - def insert_body_item(self, index, item): - return self.insertBodyItem(index, item) - - def add_first_body_item(self, item): - return self.addFirstBodyItem(item) - - def add_last_body_item(self, item): - return self.addLastBodyItem(item) - - def append_body_item(self, item): - return self.appendBodyItem(item) - - -@jpype.JImplementationFor("it.unibo.tuprolog.core.Rule") -class _KtRule: - def __jclass_init__(cls): - pass - - @property - def head_args(self): - return self.getHeadArgs() - - @property - def head_arity(self): - return self.getHeadArity() - - def get_head_arg(self, index): - return self.getHeadArg(index) - - -@jpype.JImplementationFor("it.unibo.tuprolog.core.TermConvertible") -class _KtTermConvertible: - def __jclass_init__(cls): - pass - - def to_term(self): - return self.toTerm() - @jpype.JImplementationFor("it.unibo.tuprolog.core.Substitution") class _KtSubstitution: def __jclass_init__(cls): pass - def apply_to(self, term): - return self.applyTo(term) - - def get_original(self, variable): - return self.getOriginal(variable) - - def get_by_name(self, name): - return self.getByName(name) - def __add__(self, other): return self.plus(other) diff --git a/tuprolog/jvmutils.py b/tuprolog/jvmutils.py index d7bcf13..5cc7482 100644 --- a/tuprolog/jvmutils.py +++ b/tuprolog/jvmutils.py @@ -231,6 +231,7 @@ def __jclass_init__(self): property_name = snake_case[4:] if member._isBeanAccessor(): getter = member + # Attempt to find paired bean setter setter_name = "set" + name.removeprefix("get") setter = getattr(self, setter_name, None) if setter is not None and isinstance(setter, JMethodClass) and setter._isBeanMutator(): diff --git a/tuprolog/solve/_ktadapt.py b/tuprolog/solve/_ktadapt.py index 6433874..94c7361 100644 --- a/tuprolog/solve/_ktadapt.py +++ b/tuprolog/solve/_ktadapt.py @@ -8,12 +8,6 @@ from tuprolog.pyutils import iterable_or_varargs -@jpype.JImplementationFor("it.unibo.tuprolog.solve.SolverFactory") -class _KtSolverFactory: - def __jclass_init__(self): - pass - - @jpype.JImplementationFor("it.unibo.tuprolog.solve.SolveOptions") class _KtSolveOptions: @@ -64,56 +58,6 @@ def __getitem__(self, item, default=None): return KeyError(f"No such option: {item}") -@jpype.JImplementationFor("it.unibo.tuprolog.solve.ExecutionContextAware") -class _KtExecutionContextAware: - def __jclass_init__(self): - pass - - @property - def libraries(self): - return self.getLibraries() - - @property - def flags(self): - return self.getFlags() - - @property - def static_kb(self): - return self.getStaticKb() - - @property - def dynamic_kb(self): - return self.getDynamicKb() - - @property - def operators(self): - return self.getOperators() - - @property - def input_channels(self): - return self.getInputChannles() - - @property - def output_channels(self): - return self.getOutputChannles() - - @property - def standard_output(self): - return self.getStandardOutput() - - @property - def standard_input(self): - return self.getStandardInput() - - @property - def standard_error(self): - return self.getStandardError() - - @property - def warnings(self): - return self.getWarnings() - - @jpype.JImplementationFor("it.unibo.tuprolog.solve.Solver") class _KtSolver: def __jclass_init__(self): @@ -141,51 +85,12 @@ class _KtMutableSolver: def __jclass_init__(self): pass - def load_library(self, library): - return self.loadLibrary(library) - - def unload_library(self, library): - return self.unloadLibrary(library) - - def set_libraries(self, libraries): - return self.setLibraries(libraries) - - def load_static_kb(self, theory): - return self.loadStaticKb(theory) - def load_static_clauses(self, *clauses): return iterable_or_varargs(clauses, lambda cs: self.loadStaticClauses(cs)) - def append_static_kb(self, theory): - return self.appendStaticKb(theory) - - def reset_static_kb(self): - return self.resetStaticKb() - - def load_dynamic_kb(self, theory): - return self.loadDynamicKb(theory) - def load_dynamic_clauses(self, *clauses): return iterable_or_varargs(clauses, lambda cs: self.loadDynamicClauses(cs)) - def append_dynamic_kb(self, theory): - return self.appendDynamicKb(theory) - - def reset_dynamic_kb(self): - return self.resetDynamicKb() - - def assert_a(self, clause): - return self.assertA(clause) - - def assert_z(self, clause): - return self.assertZ(clause) - - def retract_all(self, clause): - return self.retractAll(clause) - - def set_flag(self, *args): - return self.setFlag(*args) - @property def standard_output(self): return self.getStandardOutput() @@ -219,40 +124,4 @@ def warnings(self, channel): return self.setWarnings(channel) -@jpype.JImplementationFor("it.unibo.tuprolog.solve.Solution") -class _KtSolution: - def __jclass_init__(self): - pass - - @property - def is_yes(self): - return self.isYes() - - @property - def is_no(self): - return self.isNo() - - @property - def is_halt(self): - return self.isHalt() - - @property - def substitution(self): - return self.getSubstitution() - - @property - def exception(self): - return self.getExecption() - - @property - def solved_query(self): - return self.getSolvedQuery() - - def clean_up(self): - return self.cleanUp() - - def value_of(self, variable): - return self.valueOf(variable) - - logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.solve.*") diff --git a/tuprolog/theory/_ktadapt.py b/tuprolog/theory/_ktadapt.py index 6273dfd..b8aadd9 100644 --- a/tuprolog/theory/_ktadapt.py +++ b/tuprolog/theory/_ktadapt.py @@ -11,16 +11,6 @@ class _KtTheory: def __jclass_init__(cls): Sized.register(cls) - @property - def is_mutable(self): - return self.isMutable() - - def to_mutable_theory(self): - return self.toMutableTheory() - - def to_immutable_theory(self): - return self.toImmutableTheory() - @jpype.JOverride def getClauses(self): return protect_iterable(self.getClauses_()) @@ -99,30 +89,4 @@ def to_string(self, as_prolog_text=False): return self.toString(as_prolog_text) -@jpype.JImplementationFor("it.unibo.tuprolog.theory.RetractResult") -class _KtRetractResult: - def __jclass_init__(cls): - pass - - @property - def is_success(self): - return self.isSuccess() - - @property - def is_failure(self): - return self.isFailure() - - @property - def theory(self): - return self.getTheory() - - @property - def clauses(self): - return self.getClauses() - - @property - def first_clause(self): - return self.getFirstClause() - - logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.theory.*") diff --git a/tuprolog/unify/__init__.py b/tuprolog/unify/__init__.py index d7df192..c50e649 100644 --- a/tuprolog/unify/__init__.py +++ b/tuprolog/unify/__init__.py @@ -4,7 +4,6 @@ # noinspection PyUnresolvedReferences import it.unibo.tuprolog.unify as _unify from tuprolog.core import Term, Substitution -from ._ktadapt import * Unificator = _unify.Unificator diff --git a/tuprolog/unify/_ktadapt.py b/tuprolog/unify/_ktadapt.py deleted file mode 100644 index 69a83db..0000000 --- a/tuprolog/unify/_ktadapt.py +++ /dev/null @@ -1,15 +0,0 @@ -from tuprolog import logger -import jpype - - -@jpype.JImplementationFor("it.unibo.tuprolog.unify.Unificator") -class _KtUnificator: - def __jclass_init__(cls): - pass - - @property - def context(self): - return self.getContext() - - -logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.unify.*") diff --git a/tuprolog/unify/exception/__init__.py b/tuprolog/unify/exception/__init__.py index 18f1ec9..e789dae 100644 --- a/tuprolog/unify/exception/__init__.py +++ b/tuprolog/unify/exception/__init__.py @@ -3,7 +3,6 @@ import jpype.imports # noinspection PyUnresolvedReferences import it.unibo.tuprolog.unify.exception as _exceptions -from ._ktadapt import * NoUnifyException = _exceptions.NoUnifyException diff --git a/tuprolog/unify/exception/_ktadapt.py b/tuprolog/unify/exception/_ktadapt.py deleted file mode 100644 index c04f1d3..0000000 --- a/tuprolog/unify/exception/_ktadapt.py +++ /dev/null @@ -1,19 +0,0 @@ -from tuprolog import logger -import jpype - - -@jpype.JImplementationFor("it.unibo.tuprolog.unify.exception.NoUnifyException") -class _KtNoUnifyException: - def __jclass_init__(cls): - pass - - @property - def term1(self): - return self.getTerm1() - - @property - def term2(self): - return self.getTerm2() - - -logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.unify.exception.*") diff --git a/tuprolog/utils/__init__.py b/tuprolog/utils/__init__.py index cbbd797..4e78706 100644 --- a/tuprolog/utils/__init__.py +++ b/tuprolog/utils/__init__.py @@ -1,5 +1,4 @@ from tuprolog import logger -from ._ktadapt import * # noinspection PyUnresolvedReferences import jpype.imports # noinspection PyUnresolvedReferences diff --git a/tuprolog/utils/_ktadapt.py b/tuprolog/utils/_ktadapt.py deleted file mode 100644 index ecff775..0000000 --- a/tuprolog/utils/_ktadapt.py +++ /dev/null @@ -1,24 +0,0 @@ -from tuprolog import logger -import jpype - - -@jpype.JImplementationFor("it.unibo.tuprolog.utils.Taggable") -class _KtTaggable: - def __jclass_init__(cls): - pass - - @property - def tags(self): - return self.getTags() - - def get_tag(self, name): - return self.getTag(name) - - def replace_tags(self, tags): - return self.replaceTags(tags) - - def contains_tag(self, name): - return self.containsTag(name) - - -logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.utils.*") From 4b7231375130352cad9b1351898a7e711337accf Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 5 Oct 2023 00:26:41 +0200 Subject: [PATCH 115/154] Update README --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 7b6fe1c..0221964 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Experimental porting of [2P-Kt](https://github.com/tuProlog/2p-kt) on Python, via [JPype](https://jpype.readthedocs.io). -> This is a __work in progress__. 2PPy is not ready for general availability, yet. +> This is a __work in progress__. ## Introduction @@ -56,7 +56,12 @@ other aimed at (de)serialising terms theories, namely `tuprolog.theory.serializ 1. Import `tuprolog.*` modules in your Python scripts 1. *Note for the expert users:* 2ppy downloads its own [Java Virtual Machine](https://en.wikipedia.org/wiki/Java_virtual_machine) in order to call Java bytecode from python. If you install the package with sdist, it's downloaded during install. If you use the binary wheels packaging, it's downloaded on first import of the `tuprolog` package. -### How to develop 2PPy +### How to use 2PPy as interactive REPL + +1. Python shell mode: `python -m tuprolog` +1. Logic solver [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop): WIP + +## How to contribute to 2PPy 1. Restore Python dev dependencies via PIP, by running: ```bash @@ -72,8 +77,3 @@ other aimed at (de)serialising terms theories, namely `tuprolog.theory.serializ 1. Build the package with `python -m build` 1. Install the package locally with `python setup.py install` 1. Print the package version, computed from git tags with `python -m setuptools_git_versioning` - -### How to use 2PPy as an executable - -1. Python shell mode: WIP -1. Logic solver [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop): WIP From 939c6303c5edc13add0cd839f74a2f6b17b2084e Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 5 Oct 2023 13:03:25 +0200 Subject: [PATCH 116/154] Chores on tuprolog.core --- test/solve/test_prolog_with_resolution.py | 21 +++++++++++++++++++++ tuprolog/__init__.py | 6 +++--- tuprolog/core/__init__.py | 7 ++++++- tuprolog/core/_ktadapt.py | 5 +---- tuprolog/jvmioutils.py | 12 ++++-------- tuprolog/jvmutils.py | 10 +++++----- tuprolog/utils/__init__.py | 6 +++--- 7 files changed, 43 insertions(+), 24 deletions(-) create mode 100644 test/solve/test_prolog_with_resolution.py diff --git a/test/solve/test_prolog_with_resolution.py b/test/solve/test_prolog_with_resolution.py new file mode 100644 index 0000000..6444d90 --- /dev/null +++ b/test/solve/test_prolog_with_resolution.py @@ -0,0 +1,21 @@ +import unittest +from tuprolog.core import rule, struct, var, fact, atom +from tuprolog.solve import * + +class TestPrologWithResolution(unittest.TestCase): + def test_abraham_family_tree(self): + program = [ + rule( + struct("ancestor", var("X"), var("Y")), # :- + struct("parent", var("X"), var("Y")) + ), + rule( + struct("ancestor", var("X"), var("Y")), # :- + struct("parent", var("X"), var("Z")), + struct("ancestor", var("Z"), var("Y")) + ), + fact(struct("parent", atom("abraham"), atom("isaac"))), + fact(struct("parent", atom("isaac"), atom("jacob"))), + fact(struct("parent", atom("jacob"), atom("joseph"))), + ] + # TODO: solve diff --git a/tuprolog/__init__.py b/tuprolog/__init__.py index 6b94d87..6d9836d 100644 --- a/tuprolog/__init__.py +++ b/tuprolog/__init__.py @@ -1,10 +1,11 @@ import os import logging -# noinspection PyUnresolvedReferences import jpype import jpype.imports from .libs import JAVA_HOME, CLASSPATH, install_java_if_missing + +# Override the JAVA_HOME environment variable to use the locally installed JDK os.environ['JAVA_HOME'] = str(JAVA_HOME) logger = logging.getLogger('tuprolog') @@ -15,8 +16,7 @@ install_java_if_missing() jpype.startJVM(classpath=jars) -# noinspection PyUnresolvedReferences -from it.unibo import tuprolog as _tuprolog +from it.unibo import tuprolog as _tuprolog # type: ignore Info = _tuprolog.Info diff --git a/tuprolog/core/__init__.py b/tuprolog/core/__init__.py index bf78a85..40b7ad2 100644 --- a/tuprolog/core/__init__.py +++ b/tuprolog/core/__init__.py @@ -1,3 +1,4 @@ +from typing import Iterable, Dict, Tuple as PyTuple, Union from decimal import Decimal from tuprolog import logger from ._ktadapt import * @@ -6,9 +7,11 @@ import it.unibo.tuprolog.core as _core # type: ignore from tuprolog.pyutils import iterable_or_varargs from tuprolog.jvmutils import jiterable, jmap -from typing import Iterable, Dict, Tuple as PyTuple +from ._ktmath import * +Applicable = _core.Applicable + Atom = _core.Atom Block = _core.Block @@ -69,6 +72,8 @@ Var = _core.Var +Variabled = _core.Variabled + @jpype.JImplements(TermConvertible) class AbstractTermConvertible(object): diff --git a/tuprolog/core/_ktadapt.py b/tuprolog/core/_ktadapt.py index daf58c4..53dd666 100644 --- a/tuprolog/core/_ktadapt.py +++ b/tuprolog/core/_ktadapt.py @@ -1,13 +1,10 @@ -from decimal import Decimal from tuprolog import logger import jpype -from ._ktmath import big_integer, big_decimal, BigInteger, BigDecimal -from tuprolog.utils import * +from ._ktmath import big_integer, BigInteger, python_integer, python_decimal from typing import Sized, Callable from tuprolog.jvmutils import jiterable from tuprolog.pyutils import iterable_or_varargs from tuprolog.jvmutils import kfunction -from ._ktmath import * @jpype.JImplementationFor("it.unibo.tuprolog.core.Term") diff --git a/tuprolog/jvmioutils.py b/tuprolog/jvmioutils.py index 221d512..ca346c5 100644 --- a/tuprolog/jvmioutils.py +++ b/tuprolog/jvmioutils.py @@ -1,14 +1,10 @@ from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype -# noinspection PyUnresolvedReferences -import jpype.imports -# noinspection PyUnresolvedReferences -import java.io as _jio -# noinspection PyUnresolvedReferences -import java.nio.file as _jnio_file from io import IOBase, SEEK_SET from typing import Union +import jpype +import jpype.imports +import java.io as _jio # type: ignore +import java.nio.file as _jnio_file # type: ignore InputStream = _jio.InputStream diff --git a/tuprolog/jvmutils.py b/tuprolog/jvmutils.py index 5cc7482..fac7190 100644 --- a/tuprolog/jvmutils.py +++ b/tuprolog/jvmutils.py @@ -1,7 +1,5 @@ -from typing import Iterable as PyIterable -from typing import Iterator as PyIterator -from typing import Mapping, MutableMapping, Callable, Any from tuprolog import logger +from typing import Iterable as PyIterable, Iterator as PyIterator, Mapping, MutableMapping, Callable, Any import jpype import jpype.imports from _jpype import _JObject as JObjectClass, _JMethod as JMethodClass # type: ignore @@ -10,8 +8,6 @@ import kotlin as _kotlin # type: ignore import kotlin.sequences as _ksequences # type: ignore import it.unibo.tuprolog.utils as _tuprolog_utils # type: ignore - - from .jvmioutils import * @@ -211,6 +207,10 @@ def to_snake_case(camel_str: str) -> str: @jpype.JImplementationFor("java.lang.Object") class _KtObjectWithSmartPythonicAccessors: + """ + This class provides every Java imported type with Pythonic versions of its methods and properties, + unless pythonic versions would conflict with existing members. + """ def __jclass_init__(self): members = dir(self) members_set = set(members) diff --git a/tuprolog/utils/__init__.py b/tuprolog/utils/__init__.py index 4e78706..2085d89 100644 --- a/tuprolog/utils/__init__.py +++ b/tuprolog/utils/__init__.py @@ -1,8 +1,8 @@ from tuprolog import logger -# noinspection PyUnresolvedReferences import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.utils as _utils +import it.unibo.tuprolog.utils as _utils # type: ignore + +Castable = _utils.Castable Taggable = _utils.Taggable From 8d93dcf7abb5bc1d47c73f7b05de90cf4e9c184c Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 5 Oct 2023 16:00:48 +0200 Subject: [PATCH 117/154] Improve readme documentation --- README.md | 73 +++++++++++++------ .../test_prolog.py} | 0 2 files changed, 52 insertions(+), 21 deletions(-) rename test/{solve/test_prolog_with_resolution.py => api/test_prolog.py} (100%) diff --git a/README.md b/README.md index 0221964..7128c03 100644 --- a/README.md +++ b/README.md @@ -8,28 +8,30 @@ Experimental porting of [2P-Kt](https://github.com/tuProlog/2p-kt) on Python, vi Object-oriented and modular ecosystem for symbolic AI and logic programming, currently featuring: -* a module for logic terms and clauses representation, namely `tuprolog.core`, +* a command-line interface, in the form of a REPL, invoked by running `python -m tuprolog` -* a module for logic unification, namely `tuprolog.unify`, +* a module for logic terms and clauses representation, namely `tuprolog.core` -* a module for in-memory indexing and storing logic theories, as well as other sorts of collections of logic clauses, namely `tuprolog.theory`, +* a module for logic unification, namely `tuprolog.unify` + +* a module for in-memory indexing and storing logic theories, as well as other sorts of collections of logic clauses, namely `tuprolog.theory` * a module providing generic API for resolution of logic queries, namely `tuprolog.solve`, currently implementing a Prolog solver -* two parsing modules: one aimed at parsing terms, namely `tuprolog.core.parsing`, and the other aimed at parsing theories, namely `tuprolog.theory.parsing`, +* two parsing modules: one aimed at parsing terms, namely `tuprolog.core.parsing`, and the other aimed at parsing theories, namely `tuprolog.theory.parsing` * two serialisation-related modules: one aimed at (de)serialising terms and clauses, namely `tuprolog.core.serialize`, and the -other aimed at (de)serialising terms theories, namely `tuprolog.theory.serialize`, +other aimed at (de)serialising terms theories, namely `tuprolog.theory.serialize` -* a module for using Prolog via a command-line interface, namely `tuprolog.repl`, +* a module that implements probabilistic logic programming and solving, namely `tuprolog.solve.problog` -* a module that implement probabilistic logic programming and solving, namely `tuprolog.solve.problog`. ## How to use 2ppy -### Use 2ppy as a library +### Installing 2ppy + +1. Install Python 3 (look into the [`pyproject.toml`](pyproject.toml) to know the exact versions supported) -1. Install Python 3 (look into the `.pyproject.toml` to know the exact versions supported) * If your system has 64-bit processor, install the Python 3 64-bit distribution, and viceversa * Ensure PIP works fine * It's suggested to use a [virtual environment](https://docs.python.org/3/library/venv.html) to install the dependencies locally @@ -53,27 +55,56 @@ other aimed at (de)serialising terms theories, namely `tuprolog.theory.serializ ```bash python3 -m pip install 2ppy ``` -1. Import `tuprolog.*` modules in your Python scripts 1. *Note for the expert users:* 2ppy downloads its own [Java Virtual Machine](https://en.wikipedia.org/wiki/Java_virtual_machine) in order to call Java bytecode from python. If you install the package with sdist, it's downloaded during install. If you use the binary wheels packaging, it's downloaded on first import of the `tuprolog` package. +### Use 2ppy as a library + +1. Import `tuprolog.*` modules in your Python scripts +1. Use the Pythonic API to write, parse or solve your logic programs. You can find some examples in the [api tests folder](test/api). + ### How to use 2PPy as interactive REPL 1. Python shell mode: `python -m tuprolog` -1. Logic solver [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop): WIP +1. Logic solver [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop): *WIP* ## How to contribute to 2PPy -1. Restore Python dev dependencies via PIP, by running: - ```bash - pip install -r requirements.txt - ``` - On __Mac OS__ this may not work as expected. - Consider running the following command instead: - ```bash - python3 -m pip -r requirements.txt - ``` +1. Install dependencies + 1. Restore Python dev dependencies via PIP, by running: + ```bash + pip install -r requirements.txt + ``` + On __Mac OS__ this may not work as expected. + Consider running the following command instead: + ```bash + python3 -m pip -r requirements.txt + ``` + 1. Install [maven](https://maven.apache.org/install.html) and make sure that the `mvn` command is available in your `PATH` 1. Write the code inside `tuprolog` and the unit tests inside `test` 1. Execute tests with `python -m pytest -p no:faulthandler` 1. Build the package with `python -m build` 1. Install the package locally with `python setup.py install` -1. Print the package version, computed from git tags with `python -m setuptools_git_versioning` +1. Optionally, print the package version, computed from git tags with `python -m setuptools_git_versioning` + +### Adopted Git flow + +The Git Flow for 2ppy consists of the following: + +- The ongoing development happens on the `develop` branch +- The `master` branch is used to display the latest released code +- Independent features are developed on their own branches, and merged into `develop` when ready +- In order to make a new release, the code should be merged on master and a new [git tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging#_annotated_tags) should be created on the release commit, following the [Semantic Versioning](https://semver.org/) semantic + As an example, the following commands can be used to make a new release: + ```bash + git checkout master + git merge develop + git tag -a v0.1.0 -m "First release" + git push origin master --tags + ``` + +#### CI/CD + +The Continuous Integration pipeline will run unit tests against some combinations of operating systems, java version for the JVM and python version. +It will also check the Python style with [flake8](https://flake8.pycqa.org/en/latest/). + +The Continuous Delivery pipeline will create a new [Github Release](https://github.com/tuProlog/2ppy/releases) and will deploy the package on [PyPI](https://pypi.org/project/2ppy/). diff --git a/test/solve/test_prolog_with_resolution.py b/test/api/test_prolog.py similarity index 100% rename from test/solve/test_prolog_with_resolution.py rename to test/api/test_prolog.py From 1960b39973aeac644a486bd1d145bf111364b15a Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 5 Oct 2023 19:03:52 +0200 Subject: [PATCH 118/154] Port and test unify module --- test/core/test_substitution.py | 13 ++++++++++- test/core/test_unify.py | 32 ++++++++++++++++++++++++++++ tuprolog/core/_ktadapt.py | 5 ++--- tuprolog/core/operators/__init__.py | 2 +- tuprolog/unify/__init__.py | 4 +--- tuprolog/unify/exception/__init__.py | 4 +--- 6 files changed, 49 insertions(+), 11 deletions(-) create mode 100644 test/core/test_unify.py diff --git a/test/core/test_substitution.py b/test/core/test_substitution.py index 86ad117..bf027f5 100644 --- a/test/core/test_substitution.py +++ b/test/core/test_substitution.py @@ -1,5 +1,5 @@ import unittest -from tuprolog.core import substitution, var, struct, FAIL +from tuprolog.core import substitution, var, struct, atom, scope class TestSubstitution(unittest.TestCase): @@ -9,3 +9,14 @@ def test_substitution_creation(self): self.assertEqual(0, len(sub)) self.assertEqual(True, sub.isSuccess()) self.assertEqual(True, sub.is_success) + + def test_substitution_application(self): + sc = scope("X", "Y") + term = struct("father", sc["X"], sc["Y"]) + sub1 = substitution({sc["X"]: atom("abraham")}) + sub2 = substitution({sc["Y"]: atom("isaac")}) + + sub = sub1 + sub2 + + result = sub.apply_to(term) + self.assertEqual("father(abraham, isaac)", result.to_string()) diff --git a/test/core/test_unify.py b/test/core/test_unify.py new file mode 100644 index 0000000..61ec3a5 --- /dev/null +++ b/test/core/test_unify.py @@ -0,0 +1,32 @@ +import unittest +from tuprolog.core import scope +from tuprolog.unify import DEFAULT_UNIFICATOR +from tuprolog.jvmutils import Pair + +class TestSubstitutionMerge(unittest.TestCase): + def test_merge_with(self): + s = scope("X", "Y", "Z") + base = s.unifier_of( + ("X", s["Y"]), + ("Y", s["Z"]), + ) + a = s.atom_of("a") + + for v_name, v in s.variables.items(): + assignment = s.unifier_of(Pair(v_name, a)) + self.assertEqual( + s.unifier_of( + ("X", a), + ("Y", a), + ("Z", a), + ), + DEFAULT_UNIFICATOR.merge(base, assignment), + ) + self.assertEqual( + s.unifier_of( + ("X", a), + ("Y", a), + ("Z", a), + ), + DEFAULT_UNIFICATOR.merge(assignment, base), + ) diff --git a/tuprolog/core/_ktadapt.py b/tuprolog/core/_ktadapt.py index 53dd666..0b3b7f8 100644 --- a/tuprolog/core/_ktadapt.py +++ b/tuprolog/core/_ktadapt.py @@ -1,10 +1,9 @@ +from typing import Sized, Callable from tuprolog import logger import jpype from ._ktmath import big_integer, BigInteger, python_integer, python_decimal -from typing import Sized, Callable -from tuprolog.jvmutils import jiterable +from tuprolog.jvmutils import jiterable, kfunction, kpair, ksequence from tuprolog.pyutils import iterable_or_varargs -from tuprolog.jvmutils import kfunction @jpype.JImplementationFor("it.unibo.tuprolog.core.Term") diff --git a/tuprolog/core/operators/__init__.py b/tuprolog/core/operators/__init__.py index 96119fe..c287d06 100644 --- a/tuprolog/core/operators/__init__.py +++ b/tuprolog/core/operators/__init__.py @@ -1,11 +1,11 @@ from tuprolog import logger from ._ktadapt import * +from functools import singledispatch import jpype.imports import it.unibo.tuprolog.core.operators as _operators # type: ignore from tuprolog.jvmutils import jiterable from tuprolog.pyutils import iterable_or_varargs from tuprolog.core import Atom, Integer, Struct, Term -from functools import singledispatch Operator = _operators.Operator diff --git a/tuprolog/unify/__init__.py b/tuprolog/unify/__init__.py index c50e649..77cf790 100644 --- a/tuprolog/unify/__init__.py +++ b/tuprolog/unify/__init__.py @@ -1,8 +1,6 @@ from tuprolog import logger -# noinspection PyUnresolvedReferences import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.unify as _unify +import it.unibo.tuprolog.unify as _unify # type: ignore from tuprolog.core import Term, Substitution diff --git a/tuprolog/unify/exception/__init__.py b/tuprolog/unify/exception/__init__.py index e789dae..4366f1e 100644 --- a/tuprolog/unify/exception/__init__.py +++ b/tuprolog/unify/exception/__init__.py @@ -1,8 +1,6 @@ from tuprolog import logger -# noinspection PyUnresolvedReferences import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.unify.exception as _exceptions +import it.unibo.tuprolog.unify.exception as _exceptions # type: ignore NoUnifyException = _exceptions.NoUnifyException From 1783c783826b99960efbfec7cd57fa0b90002583 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 5 Oct 2023 20:32:56 +0200 Subject: [PATCH 119/154] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7128c03..ea0fc56 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,8 @@ other aimed at (de)serialising terms theories, namely `tuprolog.theory.serializ ```bash python3 -m pip install 2ppy ``` -1. *Note for the expert users:* 2ppy downloads its own [Java Virtual Machine](https://en.wikipedia.org/wiki/Java_virtual_machine) in order to call Java bytecode from python. If you install the package with sdist, it's downloaded during install. If you use the binary wheels packaging, it's downloaded on first import of the `tuprolog` package. +1. *Note #1 for the expert users:* 2ppy downloads its own [Java Virtual Machine](https://en.wikipedia.org/wiki/Java_virtual_machine) in order to call Java bytecode from python. If you install the package with sdist, it's downloaded during install. If you use the binary wheels packaging, it's downloaded on first import of the `tuprolog` package. +2. *Note #2 for the expert users:* The JVM version can be chosen by setting the `JAVA_VERSION` environment variable before downloading the JVM for the first time. ### Use 2ppy as a library From deeb792ed2e34a1a1388366255c89f3d1c6e9d48 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Fri, 6 Oct 2023 13:58:12 +0200 Subject: [PATCH 120/154] Fix typos --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ea0fc56..095b6c6 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ other aimed at (de)serialising terms theories, namely `tuprolog.theory.serializ 1. Import `tuprolog.*` modules in your Python scripts 1. Use the Pythonic API to write, parse or solve your logic programs. You can find some examples in the [api tests folder](test/api). -### How to use 2PPy as interactive REPL +### Use 2PPy as an interactive REPL 1. Python shell mode: `python -m tuprolog` 1. Logic solver [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop): *WIP* @@ -94,7 +94,7 @@ The Git Flow for 2ppy consists of the following: - The ongoing development happens on the `develop` branch - The `master` branch is used to display the latest released code - Independent features are developed on their own branches, and merged into `develop` when ready -- In order to make a new release, the code should be merged on master and a new [git tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging#_annotated_tags) should be created on the release commit, following the [Semantic Versioning](https://semver.org/) semantic +- In order to make a new release, the code should be merged on master and a new [git tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging#_annotated_tags) should be created on the release commit, following the [Semantic Versioning](https://semver.org/) semantic. As an example, the following commands can be used to make a new release: ```bash git checkout master @@ -105,7 +105,7 @@ The Git Flow for 2ppy consists of the following: #### CI/CD -The Continuous Integration pipeline will run unit tests against some combinations of operating systems, java version for the JVM and python version. +The Continuous Integration pipeline will run unit tests against some combinations of operating systems, supported java versions for the JVM and supported python versions. It will also check the Python style with [flake8](https://flake8.pycqa.org/en/latest/). The Continuous Delivery pipeline will create a new [Github Release](https://github.com/tuProlog/2ppy/releases) and will deploy the package on [PyPI](https://pypi.org/project/2ppy/). From bce9e89e4d239c1599d00fbf010c0b91d9698823 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:32:28 +0200 Subject: [PATCH 121/154] Sort imports --- test/core/test_visitors.py | 4 +- tuprolog/__init__.py | 2 +- tuprolog/core/__init__.py | 12 ++--- tuprolog/core/formatters.py | 6 +-- tuprolog/core/operators/__init__.py | 8 +-- tuprolog/core/operators/_ktadapt.py | 4 +- tuprolog/core/parsing/__init__.py | 6 +-- tuprolog/core/visitors.py | 53 +++++++++---------- tuprolog/jvmioutils.py | 10 ++-- tuprolog/jvmutils.py | 2 +- tuprolog/solve/__init__.py | 12 ++--- tuprolog/solve/channel/__init__.py | 13 ++--- tuprolog/solve/data/__init__.py | 11 ++-- tuprolog/solve/exception/__init__.py | 4 +- .../solve/exception/error/domain/__init__.py | 6 +-- .../exception/error/evaluation/__init__.py | 6 +-- .../exception/error/existence/__init__.py | 6 +-- .../exception/error/instantiation/__init__.py | 8 ++- .../solve/exception/error/message/__init__.py | 8 ++- .../exception/error/permission/__init__.py | 8 ++- .../error/representation/__init__.py | 10 ++-- .../solve/exception/error/syntax/__init__.py | 8 ++- .../solve/exception/error/system/__init__.py | 8 ++- .../solve/exception/error/type/__init__.py | 8 ++- tuprolog/solve/exception/warning/__init__.py | 10 ++-- tuprolog/solve/flags/__init__.py | 8 ++- tuprolog/solve/function/__init__.py | 8 ++- tuprolog/solve/library/__init__.py | 9 ++-- tuprolog/solve/library/exception/__init__.py | 4 +- tuprolog/solve/plp/__init__.py | 8 ++- tuprolog/solve/primitive/__init__.py | 9 ++-- tuprolog/solve/problog/operators.py | 4 +- tuprolog/solve/sideffcts/__init__.py | 28 ++-------- tuprolog/solve/stdlib/__init__.py | 4 +- tuprolog/solve/stdlib/function/__init__.py | 4 +- tuprolog/solve/stdlib/primitive/__init__.py | 4 +- tuprolog/solve/stdlib/rule/__init__.py | 6 +-- tuprolog/theory/__init__.py | 12 ++--- tuprolog/theory/parsing/__init__.py | 10 ++-- tuprolog/unify/__init__.py | 2 +- 40 files changed, 133 insertions(+), 220 deletions(-) diff --git a/test/core/test_visitors.py b/test/core/test_visitors.py index c2ecbf2..354188d 100644 --- a/test/core/test_visitors.py +++ b/test/core/test_visitors.py @@ -1,8 +1,8 @@ import unittest -from tuprolog.core import * +from tuprolog.core import Atom, Integer, Var from tuprolog.core.visitors import AbstractTermVisitor import jpype.imports -import kotlin.jvm.functions as _functions +import kotlin.jvm.functions as _functions # type: ignore import unittest from tuprolog.core import * diff --git a/tuprolog/__init__.py b/tuprolog/__init__.py index 6d9836d..0722d48 100644 --- a/tuprolog/__init__.py +++ b/tuprolog/__init__.py @@ -1,7 +1,6 @@ import os import logging import jpype -import jpype.imports from .libs import JAVA_HOME, CLASSPATH, install_java_if_missing @@ -16,6 +15,7 @@ install_java_if_missing() jpype.startJVM(classpath=jars) +import jpype.imports from it.unibo import tuprolog as _tuprolog # type: ignore Info = _tuprolog.Info diff --git a/tuprolog/core/__init__.py b/tuprolog/core/__init__.py index 40b7ad2..1ea9ece 100644 --- a/tuprolog/core/__init__.py +++ b/tuprolog/core/__init__.py @@ -1,13 +1,13 @@ from typing import Iterable, Dict, Tuple as PyTuple, Union from decimal import Decimal +from jpype import JImplements, JOverride from tuprolog import logger -from ._ktadapt import * -import jpype -import jpype.imports -import it.unibo.tuprolog.core as _core # type: ignore from tuprolog.pyutils import iterable_or_varargs from tuprolog.jvmutils import jiterable, jmap +from ._ktadapt import * from ._ktmath import * +import jpype.imports +import it.unibo.tuprolog.core as _core # type: ignore Applicable = _core.Applicable @@ -75,9 +75,9 @@ Variabled = _core.Variabled -@jpype.JImplements(TermConvertible) +@JImplements(TermConvertible) class AbstractTermConvertible(object): - @jpype.JOverride + @JOverride def toTerm(self): raise NotImplementedError() diff --git a/tuprolog/core/formatters.py b/tuprolog/core/formatters.py index 52de53d..1a90964 100644 --- a/tuprolog/core/formatters.py +++ b/tuprolog/core/formatters.py @@ -1,9 +1,7 @@ from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype -import jpype.imports from tuprolog.core import TermFormatter -import it.unibo.tuprolog.core.impl as _impl +import jpype.imports +import it.unibo.tuprolog.core.impl as _impl # type: ignore DefaultTermFormatter = _impl.SimpleTermFormatter diff --git a/tuprolog/core/operators/__init__.py b/tuprolog/core/operators/__init__.py index c287d06..1bb2893 100644 --- a/tuprolog/core/operators/__init__.py +++ b/tuprolog/core/operators/__init__.py @@ -1,11 +1,11 @@ -from tuprolog import logger -from ._ktadapt import * from functools import singledispatch -import jpype.imports -import it.unibo.tuprolog.core.operators as _operators # type: ignore +from tuprolog import logger from tuprolog.jvmutils import jiterable from tuprolog.pyutils import iterable_or_varargs from tuprolog.core import Atom, Integer, Struct, Term +from ._ktadapt import * +import jpype.imports +import it.unibo.tuprolog.core.operators as _operators # type: ignore Operator = _operators.Operator diff --git a/tuprolog/core/operators/_ktadapt.py b/tuprolog/core/operators/_ktadapt.py index 7a9a557..8412c9a 100644 --- a/tuprolog/core/operators/_ktadapt.py +++ b/tuprolog/core/operators/_ktadapt.py @@ -1,8 +1,8 @@ from tuprolog import logger -import jpype +from jpype import JImplementationFor -@jpype.JImplementationFor("it.unibo.tuprolog.core.operators.OperatorSet") +@JImplementationFor("it.unibo.tuprolog.core.operators.OperatorSet") class _KtOperatorSet: def __jclass_init__(cls): pass diff --git a/tuprolog/core/parsing/__init__.py b/tuprolog/core/parsing/__init__.py index 6901b8e..1f27876 100644 --- a/tuprolog/core/parsing/__init__.py +++ b/tuprolog/core/parsing/__init__.py @@ -1,11 +1,11 @@ from typing import Union, Iterable from tuprolog import logger -from ._ktadapt import * -import jpype.imports -import it.unibo.tuprolog.core.parsing as _parsing # type: ignore from tuprolog.jvmutils import InputStream from tuprolog.core import Term, Struct, Constant, Var, Atom, Numeric, Integer, Real, Clause from tuprolog.core.operators import OperatorSet, DEFAULT_OPERATORS +from ._ktadapt import * +import jpype.imports +import it.unibo.tuprolog.core.parsing as _parsing # type: ignore TermParser = _parsing.TermParser diff --git a/tuprolog/core/visitors.py b/tuprolog/core/visitors.py index 90a99fd..312d1bf 100644 --- a/tuprolog/core/visitors.py +++ b/tuprolog/core/visitors.py @@ -1,103 +1,102 @@ +from jpype import JImplements, JOverride from tuprolog import logger -import jpype -# noinspection PyUnresolvedReferences import jpype.imports -import it.unibo.tuprolog.core as _core +import it.unibo.tuprolog.core as _core # type: ignore TermVisitor = _core.TermVisitor -@jpype.JImplements(TermVisitor) +@JImplements(TermVisitor) class AbstractTermVisitor(object): - @jpype.JOverride + @JOverride def defaultValue(self, term): raise NotImplementedError() - @jpype.JOverride + @JOverride def visitTerm(self, term): return TermVisitor.visitTerm(self, term) - @jpype.JOverride + @JOverride def visitVar(self, term): return TermVisitor.visitVar(self, term) - @jpype.JOverride + @JOverride def visitConstant(self, term): return TermVisitor.visitConstant(self, term) - @jpype.JOverride + @JOverride def visitStruct(self, term): return TermVisitor.visitStruct(self, term) - @jpype.JOverride + @JOverride def visitCollection(self, term): return TermVisitor.visitCollection(self, term) - @jpype.JOverride + @JOverride def visitAtom(self, term): return TermVisitor.visitAtom(self, term) - @jpype.JOverride + @JOverride def visitTruth(self, term): return TermVisitor.visitTruth(self, term) - @jpype.JOverride + @JOverride def visitNumeric(self, term): return TermVisitor.visitNumeric(self, term) - @jpype.JOverride + @JOverride def visitInteger(self, term): return TermVisitor.visitInteger(self, term) - @jpype.JOverride + @JOverride def visitReal(self, term): return TermVisitor.visitReal(self, term) - @jpype.JOverride + @JOverride def visitBlock(self, term): return TermVisitor.visitBlock(self, term) - @jpype.JOverride + @JOverride def visitEmpty(self, term): return TermVisitor.visitEmpty(self, term) - @jpype.JOverride + @JOverride def visitEmptyBlock(self, term): return TermVisitor.visitEmptyBlock(self, term) - @jpype.JOverride + @JOverride def visitList(self, term): return TermVisitor.visitList(self, term) - @jpype.JOverride + @JOverride def visitCons(self, term): return TermVisitor.visitCons(self, term) - @jpype.JOverride + @JOverride def visitEmptyList(self, term): return TermVisitor.visitEmptyList(self, term) - @jpype.JOverride + @JOverride def visitTuple(self, term): return TermVisitor.visitTuple(self, term) - @jpype.JOverride + @JOverride def visitIndicator(self, term): return TermVisitor.visitIndicator(self, term) - @jpype.JOverride + @JOverride def visitClause(self, term): return TermVisitor.visitClause(self, term) - @jpype.JOverride + @JOverride def visitRule(self, term): return TermVisitor.visitRule(self, term) - @jpype.JOverride + @JOverride def visitFact(self, term): return TermVisitor.visitFact(self, term) - @jpype.JOverride + @JOverride def visitDirective(self, term): return TermVisitor.visitDirective(self, term) diff --git a/tuprolog/jvmioutils.py b/tuprolog/jvmioutils.py index ca346c5..35040e5 100644 --- a/tuprolog/jvmioutils.py +++ b/tuprolog/jvmioutils.py @@ -1,7 +1,7 @@ -from tuprolog import logger -from io import IOBase, SEEK_SET from typing import Union -import jpype +from io import IOBase, SEEK_SET +from tuprolog import logger +from jpype import JImplementationFor, JOverride import jpype.imports import java.io as _jio # type: ignore import java.nio.file as _jnio_file # type: ignore @@ -20,12 +20,12 @@ Paths = _jnio_file.Paths -@jpype.JImplementationFor("java.io.InputStream") +@JImplementationFor("java.io.InputStream") class _JvmInputStream: def __jclass_init__(cls): IOBase.register(cls) - @jpype.JOverride + @JOverride def close(self): self._closed = True self.close_() diff --git a/tuprolog/jvmutils.py b/tuprolog/jvmutils.py index fac7190..0797f12 100644 --- a/tuprolog/jvmutils.py +++ b/tuprolog/jvmutils.py @@ -1,6 +1,7 @@ from tuprolog import logger from typing import Iterable as PyIterable, Iterator as PyIterator, Mapping, MutableMapping, Callable, Any import jpype +from .jvmioutils import * import jpype.imports from _jpype import _JObject as JObjectClass, _JMethod as JMethodClass # type: ignore import java.util as _jutils # type: ignore @@ -8,7 +9,6 @@ import kotlin as _kotlin # type: ignore import kotlin.sequences as _ksequences # type: ignore import it.unibo.tuprolog.utils as _tuprolog_utils # type: ignore -from .jvmioutils import * Arrays = _jutils.Arrays diff --git a/tuprolog/solve/__init__.py b/tuprolog/solve/__init__.py index 330789b..51079b6 100644 --- a/tuprolog/solve/__init__.py +++ b/tuprolog/solve/__init__.py @@ -1,14 +1,12 @@ +from typing import Iterable, Mapping, Any +from functools import singledispatch from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype.imports -from ._ktadapt import * -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve as _solve from tuprolog.core import Indicator, Struct, Term, Substitution, EMPTY_UNIFIER, TermFormatter from tuprolog.solve.exception import ResolutionException from tuprolog.jvmutils import jlist, jmap, JavaSystem -from functools import singledispatch -from typing import Iterable, Mapping, Any +from ._ktadapt import * +import jpype.imports +import it.unibo.tuprolog.solve as _solve # type: ignore ExecutionContext = _solve.ExecutionContext diff --git a/tuprolog/solve/channel/__init__.py b/tuprolog/solve/channel/__init__.py index ce67d3f..a9650a7 100644 --- a/tuprolog/solve/channel/__init__.py +++ b/tuprolog/solve/channel/__init__.py @@ -1,13 +1,10 @@ -from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.channel as _channel -# noinspection PyUnresolvedReferences -import kotlin.jvm.functions as _kfunctions -from tuprolog.jvmutils import jmap, kfunction from typing import Callable, Mapping from functools import singledispatch +from tuprolog import logger +from tuprolog.jvmutils import jmap, kfunction +import jpype.imports +import it.unibo.tuprolog.solve.channel as _channel # type: ignore +import kotlin.jvm.functions as _kfunctions # type: ignore Channel = _channel.Channel diff --git a/tuprolog/solve/data/__init__.py b/tuprolog/solve/data/__init__.py index 28ed54a..7d2a30e 100644 --- a/tuprolog/solve/data/__init__.py +++ b/tuprolog/solve/data/__init__.py @@ -1,12 +1,9 @@ +from typing import Mapping, Any from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.data as _data -from tuprolog.jvmutils import Map +from tuprolog.jvmutils import Map, jmap from tuprolog.pyutils import dict_or_keyword_args -from tuprolog.jvmutils import jmap -from typing import Mapping, Any +import jpype.imports +import it.unibo.tuprolog.solve.data as _data # type: ignore CustomDataStore = _data.CustomDataStore diff --git a/tuprolog/solve/exception/__init__.py b/tuprolog/solve/exception/__init__.py index 1e433c5..c03463a 100644 --- a/tuprolog/solve/exception/__init__.py +++ b/tuprolog/solve/exception/__init__.py @@ -1,8 +1,6 @@ from tuprolog import logger -# noinspection PyUnresolvedReferences import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.exception as _exceptions +import it.unibo.tuprolog.solve.exception as _exceptions # type: ignore HaltException = _exceptions.HaltException diff --git a/tuprolog/solve/exception/error/domain/__init__.py b/tuprolog/solve/exception/error/domain/__init__.py index d0f75f4..af2799a 100644 --- a/tuprolog/solve/exception/error/domain/__init__.py +++ b/tuprolog/solve/exception/error/domain/__init__.py @@ -1,11 +1,9 @@ from typing import Iterable, Union from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.exception.error as errors from tuprolog.core import Term from tuprolog.solve import ExecutionContext, Signature +import jpype.imports +import it.unibo.tuprolog.solve.exception.error as errors # type: ignore DomainError = errors.DomainError diff --git a/tuprolog/solve/exception/error/evaluation/__init__.py b/tuprolog/solve/exception/error/evaluation/__init__.py index b0e8494..f27d70c 100644 --- a/tuprolog/solve/exception/error/evaluation/__init__.py +++ b/tuprolog/solve/exception/error/evaluation/__init__.py @@ -1,11 +1,9 @@ from typing import Union from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.exception.error as errors from tuprolog.core import Term, atom from tuprolog.solve import ExecutionContext +import jpype.imports +import it.unibo.tuprolog.solve.exception.error as errors # type: ignore EvaluationError = errors.EvaluationError diff --git a/tuprolog/solve/exception/error/existence/__init__.py b/tuprolog/solve/exception/error/existence/__init__.py index bec8185..4a8f8c8 100644 --- a/tuprolog/solve/exception/error/existence/__init__.py +++ b/tuprolog/solve/exception/error/existence/__init__.py @@ -1,11 +1,9 @@ from typing import Union from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.exception.error as errors from tuprolog.core import Term, Atom from tuprolog.solve import ExecutionContext, Signature +import jpype.imports +import it.unibo.tuprolog.solve.exception.error as errors # type: ignore ExistenceError = errors.ExistenceError diff --git a/tuprolog/solve/exception/error/instantiation/__init__.py b/tuprolog/solve/exception/error/instantiation/__init__.py index 2eb929d..01c7f20 100644 --- a/tuprolog/solve/exception/error/instantiation/__init__.py +++ b/tuprolog/solve/exception/error/instantiation/__init__.py @@ -1,13 +1,11 @@ -# noinspection PyUnresolvedReferences -import jpype.imports from tuprolog import logger from tuprolog.core import Var from tuprolog.solve import ExecutionContext, Signature -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.exception.error as errors +import jpype.imports +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore -InstantiationError = errors.InstantiationError +InstantiationError = _errors.InstantiationError def instantiation_error_for_argument( diff --git a/tuprolog/solve/exception/error/message/__init__.py b/tuprolog/solve/exception/error/message/__init__.py index 45dd98e..a0b7611 100644 --- a/tuprolog/solve/exception/error/message/__init__.py +++ b/tuprolog/solve/exception/error/message/__init__.py @@ -1,13 +1,11 @@ -# noinspection PyUnresolvedReferences -import jpype.imports from tuprolog import logger from tuprolog.core import Term from tuprolog.solve import ExecutionContext -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.exception.error as errors +import jpype.imports +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore -MessageError = errors.MessageError +MessageError = _errors.MessageError def message_error(content: Term, context: ExecutionContext, cause=None) -> MessageError: diff --git a/tuprolog/solve/exception/error/permission/__init__.py b/tuprolog/solve/exception/error/permission/__init__.py index 51669ee..2a195e8 100644 --- a/tuprolog/solve/exception/error/permission/__init__.py +++ b/tuprolog/solve/exception/error/permission/__init__.py @@ -1,14 +1,12 @@ from typing import Union -# noinspection PyUnresolvedReferences -import jpype.imports from tuprolog import logger from tuprolog.core import Term from tuprolog.solve import ExecutionContext, Signature -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.exception.error as errors +import jpype.imports +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore -PermissionError = errors.PermissionError +PermissionError = _errors.PermissionError Operation = PermissionError.Operation diff --git a/tuprolog/solve/exception/error/representation/__init__.py b/tuprolog/solve/exception/error/representation/__init__.py index d9b0e68..b85e7ee 100644 --- a/tuprolog/solve/exception/error/representation/__init__.py +++ b/tuprolog/solve/exception/error/representation/__init__.py @@ -1,15 +1,11 @@ from typing import Union -# noinspection PyUnresolvedReferences -import jpype.imports - from tuprolog import logger from tuprolog.core import Term from tuprolog.solve import ExecutionContext, Signature +import jpype.imports +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.exception.error as errors - -RepresentationError = errors.RepresentationError +RepresentationError = _errors.RepresentationError Limit = RepresentationError.Limit diff --git a/tuprolog/solve/exception/error/syntax/__init__.py b/tuprolog/solve/exception/error/syntax/__init__.py index 5c2acfd..954ca89 100644 --- a/tuprolog/solve/exception/error/syntax/__init__.py +++ b/tuprolog/solve/exception/error/syntax/__init__.py @@ -1,12 +1,10 @@ -# noinspection PyUnresolvedReferences -import jpype.imports from tuprolog import logger from tuprolog.solve import ExecutionContext -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.exception.error as errors +import jpype.imports +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore -SyntaxError = errors.SyntaxError +SyntaxError = _errors.SyntaxError def syntax_error( diff --git a/tuprolog/solve/exception/error/system/__init__.py b/tuprolog/solve/exception/error/system/__init__.py index 82c610e..ff94fb7 100644 --- a/tuprolog/solve/exception/error/system/__init__.py +++ b/tuprolog/solve/exception/error/system/__init__.py @@ -1,14 +1,12 @@ -# noinspection PyUnresolvedReferences -import jpype.imports from tuprolog import logger from tuprolog.solve import ExecutionContext -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.exception.error as errors from tuprolog.solve.exception import LogicError +import jpype.imports +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore -SystemError = errors.SyntaxError +SystemError = _errors.SyntaxError def syntax_error(context: ExecutionContext, message: str, exception) -> SystemError: if isinstance(exception, LogicError): diff --git a/tuprolog/solve/exception/error/type/__init__.py b/tuprolog/solve/exception/error/type/__init__.py index e8e66f8..e5fd510 100644 --- a/tuprolog/solve/exception/error/type/__init__.py +++ b/tuprolog/solve/exception/error/type/__init__.py @@ -1,14 +1,12 @@ from typing import Union -# noinspection PyUnresolvedReferences -import jpype.imports from tuprolog import logger from tuprolog.core import Term from tuprolog.solve import ExecutionContext, Signature -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.exception.error as errors +import jpype.imports +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore -TypeError = errors.TypeError +TypeError = _errors.TypeError Type = TypeError.Expected diff --git a/tuprolog/solve/exception/warning/__init__.py b/tuprolog/solve/exception/warning/__init__.py index fe5539d..018d292 100644 --- a/tuprolog/solve/exception/warning/__init__.py +++ b/tuprolog/solve/exception/warning/__init__.py @@ -1,14 +1,12 @@ from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.exception.warning as warnings from tuprolog.core import Struct from tuprolog.solve import ExecutionContext, ResolutionException, Signature +import jpype.imports +import it.unibo.tuprolog.solve.exception.warning as _warnings # type: ignore -InitializationIssue = warnings.InitializationIssue +InitializationIssue = _warnings.InitializationIssue -MissingPredicate = warnings.MissingPredicate +MissingPredicate = _warnings.MissingPredicate def initialization_issue( diff --git a/tuprolog/solve/flags/__init__.py b/tuprolog/solve/flags/__init__.py index 85e2bd9..e9bc36e 100644 --- a/tuprolog/solve/flags/__init__.py +++ b/tuprolog/solve/flags/__init__.py @@ -1,11 +1,9 @@ +from typing import Iterable, Union, Mapping from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.flags as _flags from tuprolog.core import Term from tuprolog.jvmutils import kpair, jmap, jarray, Pair -from typing import Iterable, Union, Mapping +import jpype.imports +import it.unibo.tuprolog.solve.flags as _flags # type: ignore DoubleQuotes = _flags.DoubleQuotes diff --git a/tuprolog/solve/function/__init__.py b/tuprolog/solve/function/__init__.py index 75eb034..9b56db0 100644 --- a/tuprolog/solve/function/__init__.py +++ b/tuprolog/solve/function/__init__.py @@ -1,12 +1,10 @@ +from typing import List, Callable from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype.imports from tuprolog.core import Term from tuprolog.solve import ExecutionContext, Signature, current_time_instant, MAX_TIMEOUT from tuprolog.solve.primitive import SolveRequest -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.function as _function -from typing import List, Callable +import jpype.imports +import it.unibo.tuprolog.solve.function as _function # type: ignore LogicFunction = _function.LogicFunction diff --git a/tuprolog/solve/library/__init__.py b/tuprolog/solve/library/__init__.py index 3178c8d..89f77ae 100644 --- a/tuprolog/solve/library/__init__.py +++ b/tuprolog/solve/library/__init__.py @@ -1,16 +1,13 @@ +from typing import Union, Mapping, Iterable from functools import reduce from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype.imports from tuprolog.core.operators import OperatorSet, operator_set from tuprolog.theory import Theory, theory from tuprolog.solve import Signature from tuprolog.solve.primitive import Primitive from tuprolog.solve.function import LogicFunction -from tuprolog.jvmutils import jiterable -from typing import Union, Mapping, Iterable -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.library as _library +import jpype.imports +import it.unibo.tuprolog.solve.library as _library # type: ignore Library = _library.Library diff --git a/tuprolog/solve/library/exception/__init__.py b/tuprolog/solve/library/exception/__init__.py index 1827e16..6ec1e4f 100644 --- a/tuprolog/solve/library/exception/__init__.py +++ b/tuprolog/solve/library/exception/__init__.py @@ -1,8 +1,6 @@ from tuprolog import logger -# noinspection PyUnresolvedReferences import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.library.exception as _exception +import it.unibo.tuprolog.solve.library.exception as _exception # type: ignore AlreadyLoadedLibraryException = _exception.AlreadyLoadedLibraryException diff --git a/tuprolog/solve/plp/__init__.py b/tuprolog/solve/plp/__init__.py index 61a0679..8f42516 100644 --- a/tuprolog/solve/plp/__init__.py +++ b/tuprolog/solve/plp/__init__.py @@ -1,11 +1,9 @@ +from typing import TypeVar, Mapping, Any from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve as _solve from tuprolog.utils import Taggable from tuprolog.solve import SolveOptions, solve_options as _solve_options, MAX_TIMEOUT, ALL_SOLUTIONS -from typing import TypeVar, Mapping, Any +import jpype.imports +import it.unibo.tuprolog.solve as _solve # type: ignore ProbExtensions = _solve.ProbExtensions diff --git a/tuprolog/solve/primitive/__init__.py b/tuprolog/solve/primitive/__init__.py index d61b4ce..0c1c340 100644 --- a/tuprolog/solve/primitive/__init__.py +++ b/tuprolog/solve/primitive/__init__.py @@ -1,14 +1,11 @@ +from typing import List, Iterable, Callable from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype.imports from tuprolog.core import Term, Clause, Integer from tuprolog.solve import ExecutionContext, Signature, Solution, current_time_instant, MAX_TIMEOUT -# from tuprolog.solve.sideffcts import SideEffect from tuprolog.pyutils import iterable_or_varargs from tuprolog.jvmutils import jlist -from typing import List, Iterable, Callable -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.primitive as _primitive +import jpype.imports +import it.unibo.tuprolog.solve.primitive as _primitive # type: ignore Primitive = _primitive.Primitive diff --git a/tuprolog/solve/problog/operators.py b/tuprolog/solve/problog/operators.py index eb322cc..f71633b 100644 --- a/tuprolog/solve/problog/operators.py +++ b/tuprolog/solve/problog/operators.py @@ -1,8 +1,6 @@ from tuprolog import logger -# noinspection PyUnresolvedReferences import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.problog as _problog +import it.unibo.tuprolog.solve.problog as _problog # type: ignore Operators = _problog.Operators diff --git a/tuprolog/solve/sideffcts/__init__.py b/tuprolog/solve/sideffcts/__init__.py index 5314060..1a8c110 100644 --- a/tuprolog/solve/sideffcts/__init__.py +++ b/tuprolog/solve/sideffcts/__init__.py @@ -1,31 +1,13 @@ -from functools import reduce - +from typing import Mapping, Union, Iterable, Any from tuprolog import logger - -# noinspection PyUnresolvedReferences -import jpype -# noinspection PyUnresolvedReferences -import jpype.imports - -# noinspection PyUnresolvedReferences -from it.unibo.tuprolog.solve.sideffects import SideEffect -# noinspection PyUnresolvedReferences -from it.unibo.tuprolog.solve.sideffects import SideEffectFactory -# noinspection PyUnresolvedReferences -from it.unibo.tuprolog.solve.sideffects import SideEffectsBuilder - -# noinspection PyUnresolvedReferences from tuprolog.core import Clause, Term -# noinspection PyUnresolvedReferences +from tuprolog.pyutils import iterable_or_varargs, dict_or_keyword_args +from tuprolog.jvmutils import jlist, jmap from tuprolog.core.operators import Operator, OperatorSet -# noinspection PyUnresolvedReferences from tuprolog.solve.library import Library, libraries as new_libraries -# noinspection PyUnresolvedReferences from tuprolog.solve.channel import InputChannel, OutputChannel -from tuprolog.pyutils import iterable_or_varargs, dict_or_keyword_args -from tuprolog.jvmutils import jlist, jmap - -from typing import Mapping, Union, Iterable, Any +import jpype.imports +from it.unibo.tuprolog.solve.sideffects import SideEffect # type: ignore def _forward_iterable_or_varargs(callable, args, *callable_args): diff --git a/tuprolog/solve/stdlib/__init__.py b/tuprolog/solve/stdlib/__init__.py index 1d7a1d6..e583d78 100644 --- a/tuprolog/solve/stdlib/__init__.py +++ b/tuprolog/solve/stdlib/__init__.py @@ -1,8 +1,6 @@ from tuprolog import logger -# noinspection PyUnresolvedReferences import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.stdlib as _stdlib +import it.unibo.tuprolog.solve.stdlib as _stdlib # type: ignore CommonBuiltins = _stdlib.CommonBuiltins diff --git a/tuprolog/solve/stdlib/function/__init__.py b/tuprolog/solve/stdlib/function/__init__.py index f544358..7211f49 100644 --- a/tuprolog/solve/stdlib/function/__init__.py +++ b/tuprolog/solve/stdlib/function/__init__.py @@ -1,8 +1,6 @@ from tuprolog import logger -# noinspection PyUnresolvedReferences import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.stdlib.function as _function +import it.unibo.tuprolog.solve.stdlib.function as _function # type: ignore AbsoluteValue = _function.AbsoluteValue.INSTANCE diff --git a/tuprolog/solve/stdlib/primitive/__init__.py b/tuprolog/solve/stdlib/primitive/__init__.py index 0220484..5c4bf01 100644 --- a/tuprolog/solve/stdlib/primitive/__init__.py +++ b/tuprolog/solve/stdlib/primitive/__init__.py @@ -1,8 +1,6 @@ from tuprolog import logger -# noinspection PyUnresolvedReferences import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.stdlib.primitive as _primitive +import it.unibo.tuprolog.solve.stdlib.primitive as _primitive # type: ignore Abolish = _primitive.Abolish.INSTANCE diff --git a/tuprolog/solve/stdlib/rule/__init__.py b/tuprolog/solve/stdlib/rule/__init__.py index 29a4020..433d8ea 100644 --- a/tuprolog/solve/stdlib/rule/__init__.py +++ b/tuprolog/solve/stdlib/rule/__init__.py @@ -1,9 +1,7 @@ from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.solve.stdlib.rule as _rule from tuprolog.solve import signature +import jpype.imports +import it.unibo.tuprolog.solve.stdlib.rule as _rule # type: ignore KtAppend = _rule.Append diff --git a/tuprolog/theory/__init__.py b/tuprolog/theory/__init__.py index 9b7a07f..59ac08b 100644 --- a/tuprolog/theory/__init__.py +++ b/tuprolog/theory/__init__.py @@ -1,12 +1,10 @@ -from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.theory as _theory -import it.unibo.tuprolog.unify as _unify from typing import Iterable, Union +from tuprolog import logger from tuprolog.core import Clause +from tuprolog.unify import Unificator from ._ktadapt import * +import jpype.imports +import it.unibo.tuprolog.theory as _theory # type: ignore Theory = _theory.Theory @@ -14,8 +12,6 @@ RetractResult = _theory.RetractResult -Unificator = _unify.Unificator - def theory(*clauses: Union[Clause, Iterable[Clause]]) -> Theory: return iterable_or_varargs(clauses, lambda ts: Theory.of(jiterable(ts))) diff --git a/tuprolog/theory/parsing/__init__.py b/tuprolog/theory/parsing/__init__.py index ece0c7e..90117d0 100644 --- a/tuprolog/theory/parsing/__init__.py +++ b/tuprolog/theory/parsing/__init__.py @@ -1,17 +1,13 @@ +from typing import Union, Iterable from tuprolog import logger -# noinspection PyUnresolvedReferences -import jpype -# noinspection PyUnresolvedReferences -import jpype.imports -# noinspection PyUnresolvedReferences -import it.unibo.tuprolog.theory.parsing as _parsing from tuprolog.core import Clause from tuprolog.core.parsing import _factory from tuprolog.theory import Theory from tuprolog.jvmutils import InputStream from tuprolog.core.operators import OperatorSet -from typing import Union, Iterable from ._ktadapt import * +import jpype.imports +import it.unibo.tuprolog.theory.parsing as _parsing # type: ignore ClausesParser = _parsing.ClausesParser diff --git a/tuprolog/unify/__init__.py b/tuprolog/unify/__init__.py index 77cf790..65d22ac 100644 --- a/tuprolog/unify/__init__.py +++ b/tuprolog/unify/__init__.py @@ -1,7 +1,7 @@ from tuprolog import logger +from tuprolog.core import Term, Substitution import jpype.imports import it.unibo.tuprolog.unify as _unify # type: ignore -from tuprolog.core import Term, Substitution Unificator = _unify.Unificator From d970009fcf8a103c84718753eb9ae72e958cdfa5 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:55:42 +0200 Subject: [PATCH 122/154] Remove jpype pure imports --- tuprolog/__init__.py | 1 - tuprolog/core/_ktadapt.py | 28 ++++++++++----------- tuprolog/core/comparators.py | 11 +++------ tuprolog/core/parsing/_ktadapt.py | 7 +++--- tuprolog/jvmutils.py | 38 ++++++++++++++--------------- tuprolog/solve/_ktadapt.py | 16 +++++------- tuprolog/theory/_ktadapt.py | 18 +++++++------- tuprolog/theory/parsing/_ktadapt.py | 7 +++--- 8 files changed, 58 insertions(+), 68 deletions(-) diff --git a/tuprolog/__init__.py b/tuprolog/__init__.py index 0722d48..3dbb3c9 100644 --- a/tuprolog/__init__.py +++ b/tuprolog/__init__.py @@ -1,7 +1,6 @@ import os import logging import jpype - from .libs import JAVA_HOME, CLASSPATH, install_java_if_missing # Override the JAVA_HOME environment variable to use the locally installed JDK diff --git a/tuprolog/core/_ktadapt.py b/tuprolog/core/_ktadapt.py index 0b3b7f8..87c1dd1 100644 --- a/tuprolog/core/_ktadapt.py +++ b/tuprolog/core/_ktadapt.py @@ -1,12 +1,12 @@ from typing import Sized, Callable +from jpype import JImplements, JOverride, JImplementationFor from tuprolog import logger -import jpype -from ._ktmath import big_integer, BigInteger, python_integer, python_decimal -from tuprolog.jvmutils import jiterable, kfunction, kpair, ksequence +from tuprolog.jvmutils import jiterable, kfunction from tuprolog.pyutils import iterable_or_varargs +from ._ktmath import big_integer, BigInteger, python_integer, python_decimal -@jpype.JImplementationFor("it.unibo.tuprolog.core.Term") +@JImplementationFor("it.unibo.tuprolog.core.Term") class _KtTerm: def __jclass_init__(cls): pass @@ -14,7 +14,7 @@ def __jclass_init__(cls): def __getitem__(self, item, *items): return self.get(item, *items) - @jpype.JOverride() + @JOverride() def equals(self, other, use_var_complete_name: bool = True): return self.equals_(other, use_var_complete_name) @@ -25,7 +25,7 @@ def fresh_copy(self, scope=None): return self.freshCopy(scope) -@jpype.JImplementationFor("it.unibo.tuprolog.core.Struct") +@JImplementationFor("it.unibo.tuprolog.core.Struct") class _KtStruct: def __jclass_init__(cls): pass @@ -37,7 +37,7 @@ def set_args(self, *args): return iterable_or_varargs(args, lambda xs: self.setArgs(jiterable(args))) -@jpype.JImplementationFor("it.unibo.tuprolog.core.Numeric") +@JImplementationFor("it.unibo.tuprolog.core.Numeric") class _KtNumeric: def __jclass_init__(cls): pass @@ -57,7 +57,7 @@ def to_float(self): return float(self.decimal_value) -@jpype.JImplementationFor("it.unibo.tuprolog.core.Integer") +@JImplementationFor("it.unibo.tuprolog.core.Integer") class _KtInteger: def __jclass_init__(cls): pass @@ -67,7 +67,7 @@ def value(self): return self.int_value -@jpype.JImplementationFor("it.unibo.tuprolog.core.Real") +@JImplementationFor("it.unibo.tuprolog.core.Real") class _KtReal: def __jclass_init__(cls): pass @@ -77,7 +77,7 @@ def value(self): return self.decimal_value -@jpype.JImplementationFor("it.unibo.tuprolog.core.Recursive") +@JImplementationFor("it.unibo.tuprolog.core.Recursive") class _KtRecursive: def __jclass_init__(cls): Sized.register(cls) @@ -98,7 +98,7 @@ def to_iterable(self): return self.toSequence() -@jpype.JImplementationFor("it.unibo.tuprolog.core.Clause") +@JImplementationFor("it.unibo.tuprolog.core.Clause") class _KtClause: def __jclass_init__(cls): pass @@ -113,7 +113,7 @@ def set_body_items(self, *args): return iterable_or_varargs(args, lambda xs: self.setBodyItems(jiterable(args))) -@jpype.JImplementationFor("it.unibo.tuprolog.core.Substitution") +@JImplementationFor("it.unibo.tuprolog.core.Substitution") class _KtSubstitution: def __jclass_init__(cls): pass @@ -124,7 +124,7 @@ def __add__(self, other): def __sub__(self, other): return self.minus(other) - @jpype.JOverride + @JOverride def filter(self, filter): if isinstance(filter, Callable): return self.filter_(kfunction(1)(filter)) @@ -132,7 +132,7 @@ def filter(self, filter): return self.filter_(filter) -@jpype.JImplementationFor("it.unibo.tuprolog.core.Scope") +@JImplementationFor("it.unibo.tuprolog.core.Scope") class _KtScope: def __jclass_init__(cls): pass diff --git a/tuprolog/core/comparators.py b/tuprolog/core/comparators.py index 152e9f7..22664ad 100644 --- a/tuprolog/core/comparators.py +++ b/tuprolog/core/comparators.py @@ -1,17 +1,14 @@ +from jpype import JImplements, JOverride from tuprolog import logger - -import jpype - from tuprolog.core import TermComparator - -@jpype.JImplements(TermComparator) +@JImplements(TermComparator) class AbstractTermComparator(object): - @jpype.JOverride + @JOverride def equals(self, other): return self is other - @jpype.JOverride + @JOverride def compare(self, first, second): raise NotImplementedError() diff --git a/tuprolog/core/parsing/_ktadapt.py b/tuprolog/core/parsing/_ktadapt.py index 046b218..2bd7d93 100644 --- a/tuprolog/core/parsing/_ktadapt.py +++ b/tuprolog/core/parsing/_ktadapt.py @@ -1,10 +1,9 @@ from tuprolog import logger -import jpype - +from jpype import JImplementationFor from tuprolog.jvmioutils import ensure_input_steam -@jpype.JImplementationFor("it.unibo.tuprolog.core.parsing.TermParser") +@JImplementationFor("it.unibo.tuprolog.core.parsing.TermParser") class _KtTermParser: def __jclass_init__(cls): pass @@ -50,7 +49,7 @@ def parse_clause(self, input, operators=None): return self._parse(self.parseClause, input, operators) -@jpype.JImplementationFor("it.unibo.tuprolog.core.parsing.TermReader") +@JImplementationFor("it.unibo.tuprolog.core.parsing.TermReader") class _KtTermReader: def __jclass_init__(cls): pass diff --git a/tuprolog/jvmutils.py b/tuprolog/jvmutils.py index 0797f12..6b4e594 100644 --- a/tuprolog/jvmutils.py +++ b/tuprolog/jvmutils.py @@ -1,6 +1,6 @@ -from tuprolog import logger from typing import Iterable as PyIterable, Iterator as PyIterator, Mapping, MutableMapping, Callable, Any -import jpype +from jpype import JImplements, JOverride, JConversion, JImplementationFor, JArray +from tuprolog import logger from .jvmioutils import * import jpype.imports from _jpype import _JObject as JObjectClass, _JMethod as JMethodClass # type: ignore @@ -42,14 +42,14 @@ def protect_iterable(iterable: Iterable) -> Iterable: return PyUtils.iterable(iterable) -@jpype.JImplements("java.util.Iterator", deferred=True) +@JImplements("java.util.Iterator", deferred=True) class _IteratorAdapter(object): def __init__(self, iterator): assert isinstance(iterator, PyIterator) self._iterator = iterator self._queue = None - @jpype.JOverride + @JOverride def hasNext(self): if self._queue is None: try: @@ -66,7 +66,7 @@ def hasNext(self): except StopIteration: return False - @jpype.JOverride + @JOverride def next(self): if self.hasNext(): return self._queue.pop(0) @@ -74,13 +74,13 @@ def next(self): raise NoSuchElementException() -@jpype.JImplements("java.lang.Iterable", deferred=True) +@JImplements("java.lang.Iterable", deferred=True) class _IterableAdapter(object): def __init__(self, iterable): assert isinstance(iterable, PyIterable) self._iterable = iterable - @jpype.JOverride + @JOverride def iterator(self): return _IteratorAdapter(iter(self._iterable)) @@ -94,7 +94,7 @@ def kpair(items: PyIterable) -> Pair: return Pair(first, second) -@jpype.JConversion("kotlin.Pair", instanceof=PyIterable, excludes=str) +@JConversion("kotlin.Pair", instanceof=PyIterable, excludes=str) def _kt_pair_covert(jcls, obj): return kpair(obj) @@ -109,7 +109,7 @@ def ktriple(items: PyIterable) -> Triple: return Triple(first, second, third) -@jpype.JConversion("kotlin.Triple", instanceof=PyIterable, excludes=str) +@JConversion("kotlin.Triple", instanceof=PyIterable, excludes=str) def _kt_triple_covert(jcls, obj): return ktriple(obj) @@ -129,13 +129,13 @@ def jiterable(iterable: PyIterable) -> Iterable: return _IterableAdapter(iterable) -@jpype.JConversion("java.lang.Iterable", instanceof=PyIterable, excludes=str) +@JConversion("java.lang.Iterable", instanceof=PyIterable, excludes=str) def _java_iterable_convert(jcls, obj): return jiterable(obj) def jarray(type, rank: int = 1): - return jpype.JArray(type, rank) + return JArray(type, rank) def jiterator(iterator: PyIterator) -> Iterator: @@ -156,7 +156,7 @@ def _java_obj_repr(java_object: Object) -> str: JObjectClass.__repr__ = _java_obj_repr -@jpype.JImplementationFor("kotlin.sequences.Sequence") +@JImplementationFor("kotlin.sequences.Sequence") class _KtSequence: def __jclass_init__(self): PyIterable.register(self) @@ -169,12 +169,12 @@ def ksequence(iterable: PyIterable) -> Sequence: return SequencesKt.asSequence(jiterable(iterable)) -@jpype.JConversion("kotlin.sequences.Sequence", instanceof=PyIterable, excludes=str) +@JConversion("kotlin.sequences.Sequence", instanceof=PyIterable, excludes=str) def _kt_sequence_convert(jcls, obj): return ksequence(obj) -@jpype.JImplementationFor("java.util.stream.Stream") +@JImplementationFor("java.util.stream.Stream") class _JvmStream: def __jclass_init__(self): PyIterable.register(self) @@ -183,7 +183,7 @@ def __iter__(self): return self.iterator() -@jpype.JImplementationFor("java.lang.Comparable") +@JImplementationFor("java.lang.Comparable") class _JvmComparable: def __jclass_init__(self): pass @@ -205,7 +205,7 @@ def to_snake_case(camel_str: str) -> str: return "".join("_" + x.lower() if x.isupper() and camel_str[i + 1:i + 2].islower() else x for i, x in enumerate(camel_str)).lstrip("_") -@jpype.JImplementationFor("java.lang.Object") +@JImplementationFor("java.lang.Object") class _KtObjectWithSmartPythonicAccessors: """ This class provides every Java imported type with Pythonic versions of its methods and properties, @@ -254,7 +254,7 @@ def __jclass_init__(self): members_set.add(to_add[0]) -@jpype.JImplementationFor("java.lang.Throwable") +@JImplementationFor("java.lang.Throwable") class _JvmThrowable: def __jclass_init__(self): pass @@ -282,12 +282,12 @@ def __call__(self, *args): def kfunction(arity: int): if arity not in _kt_function_classes: - @jpype.JImplements("kotlin.jvm.functions.Function" + str(arity), deferred=True) + @JImplements("kotlin.jvm.functions.Function" + str(arity), deferred=True) class _KtFunctionN(_KtFunction): def __init__(self, f): super().__init__(arity, f) - @jpype.JOverride + @JOverride def invoke(self, *args): return super().invoke(*args) diff --git a/tuprolog/solve/_ktadapt.py b/tuprolog/solve/_ktadapt.py index 94c7361..afcf48d 100644 --- a/tuprolog/solve/_ktadapt.py +++ b/tuprolog/solve/_ktadapt.py @@ -1,14 +1,10 @@ from itertools import chain - +from jpype import JImplementationFor, JOverride from tuprolog import logger - -# noinspection PyUnresolvedReferences -import jpype - from tuprolog.pyutils import iterable_or_varargs -@jpype.JImplementationFor("it.unibo.tuprolog.solve.SolveOptions") +@JImplementationFor("it.unibo.tuprolog.solve.SolveOptions") class _KtSolveOptions: _static_keys = {'lazy', 'is_lazy', 'eager', 'is_eager', 'timeout', 'limit'} @@ -58,12 +54,12 @@ def __getitem__(self, item, default=None): return KeyError(f"No such option: {item}") -@jpype.JImplementationFor("it.unibo.tuprolog.solve.Solver") +@JImplementationFor("it.unibo.tuprolog.solve.Solver") class _KtSolver: def __jclass_init__(self): pass - @jpype.JOverride + @JOverride def solve(self, goal, options=None): if options is None: return self.solve_(goal) @@ -72,7 +68,7 @@ def solve(self, goal, options=None): else: return self.solve_(goal, options) - @jpype.JOverride + @JOverride def solve_once(self, goal, options=None): if options is None: return self.solveOnce(goal) @@ -80,7 +76,7 @@ def solve_once(self, goal, options=None): return self.solveOnce(goal, options) -@jpype.JImplementationFor("it.unibo.tuprolog.solve.MutableSolver") +@JImplementationFor("it.unibo.tuprolog.solve.MutableSolver") class _KtMutableSolver: def __jclass_init__(self): pass diff --git a/tuprolog/theory/_ktadapt.py b/tuprolog/theory/_ktadapt.py index b8aadd9..ec84a60 100644 --- a/tuprolog/theory/_ktadapt.py +++ b/tuprolog/theory/_ktadapt.py @@ -1,17 +1,17 @@ +from typing import Sized +from jpype import JImplementationFor, JOverride from tuprolog import logger -import jpype from tuprolog.core import indicator as new_indicator from tuprolog.jvmutils import jiterable, protect_iterable from tuprolog.pyutils import iterable_or_varargs -from typing import Sized -@jpype.JImplementationFor("it.unibo.tuprolog.theory.Theory") +@JImplementationFor("it.unibo.tuprolog.theory.Theory") class _KtTheory: def __jclass_init__(cls): Sized.register(cls) - @jpype.JOverride + @JOverride def getClauses(self): return protect_iterable(self.getClauses_()) @@ -19,7 +19,7 @@ def getClauses(self): def clauses(self): return self.getClauses() - @jpype.JOverride + @JOverride def getRules(self): return protect_iterable(self.getRules_()) @@ -27,7 +27,7 @@ def getRules(self): def rules(self): return self.getRules() - @jpype.JOverride + @JOverride def getDirectives(self): return protect_iterable(self.getDirectives_()) @@ -58,7 +58,7 @@ def assert_a(self, clause, *clauses): def assert_z(self, clause, *clauses): self._assert(self.assertZ, clause, *clauses) - @jpype.JOverride + @JOverride def retract(self, clause, *clauses): if len(clauses) == 0: return self.retract_(clause) @@ -67,7 +67,7 @@ def retract(self, clause, *clauses): def retract_all(self, clause): return self.retractAll(clause) - @jpype.JOverride + @JOverride def abolish(self, name, arity=None, indicator=None): if name is not None: if arity is not None: @@ -78,7 +78,7 @@ def abolish(self, name, arity=None, indicator=None): return self.abolish_(indicator) raise ValueError("You should provide at least either a name-arity couple or an indicator") - @jpype.JOverride + @JOverride def equals(self, other, use_var_complete_name=True): return self.equals_(other, use_var_complete_name) diff --git a/tuprolog/theory/parsing/_ktadapt.py b/tuprolog/theory/parsing/_ktadapt.py index 2456d97..9567304 100644 --- a/tuprolog/theory/parsing/_ktadapt.py +++ b/tuprolog/theory/parsing/_ktadapt.py @@ -1,10 +1,9 @@ +from jpype import JImplementationFor from tuprolog import logger -import jpype - from tuprolog.jvmioutils import ensure_input_steam -@jpype.JImplementationFor("it.unibo.tuprolog.theory.parsing.ClausesParser") +@JImplementationFor("it.unibo.tuprolog.theory.parsing.ClausesParser") class _KtClausesParser: def __jclass_init__(cls): pass @@ -30,7 +29,7 @@ def parse_clauses(self, input, operators): -@jpype.JImplementationFor("it.unibo.tuprolog.theory.parsing.ClausesReader") +@JImplementationFor("it.unibo.tuprolog.theory.parsing.ClausesReader") class _KtClausesReader: def __jclass_init__(cls): pass From 2669cfdafe47eb5b0fb15663137acf3afe3b1c1c Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 9 Oct 2023 18:42:05 +0200 Subject: [PATCH 123/154] Refactor core, math and libs file organization --- test/core/test_formatters.py | 2 +- test/core/test_kt_math.py | 6 +- test/core/test_operators.py | 6 +- test/core/test_terms.py | 1 - test/core/test_try_except.py | 2 +- test/core/test_unify.py | 2 +- test/core/test_visitors.py | 4 +- test/post_install_test.py | 2 +- tuprolog/__main__.py | 2 +- tuprolog/core/__init__.py | 209 +----------------- tuprolog/core/{_ktadapt.py => _adapters.py} | 4 +- tuprolog/core/_api.py | 121 +++++++++++ tuprolog/core/_definitions.py | 226 ++++++++++++++++++++ tuprolog/core/comparators.py | 16 -- tuprolog/core/{formatters.py => impl.py} | 0 tuprolog/core/visitors.py | 95 -------- tuprolog/libs/__init__.py | 24 +-- tuprolog/libs/java.py | 23 ++ tuprolog/math/__init__.py | 2 + tuprolog/{core/_ktmath.py => math/_api.py} | 50 +---- tuprolog/math/_definitions.py | 60 ++++++ 21 files changed, 455 insertions(+), 402 deletions(-) rename tuprolog/core/{_ktadapt.py => _adapters.py} (97%) create mode 100644 tuprolog/core/_api.py create mode 100644 tuprolog/core/_definitions.py delete mode 100644 tuprolog/core/comparators.py rename tuprolog/core/{formatters.py => impl.py} (100%) create mode 100644 tuprolog/libs/java.py create mode 100644 tuprolog/math/__init__.py rename tuprolog/{core/_ktmath.py => math/_api.py} (70%) create mode 100644 tuprolog/math/_definitions.py diff --git a/test/core/test_formatters.py b/test/core/test_formatters.py index 25dea01..4307248 100644 --- a/test/core/test_formatters.py +++ b/test/core/test_formatters.py @@ -1,6 +1,6 @@ import unittest from tuprolog.core import * -from tuprolog.core.formatters import DefaultTermFormatter +from tuprolog.core.impl import DefaultTermFormatter class TestFormatters(unittest.TestCase): diff --git a/test/core/test_kt_math.py b/test/core/test_kt_math.py index 48bbacd..721efff 100644 --- a/test/core/test_kt_math.py +++ b/test/core/test_kt_math.py @@ -1,9 +1,7 @@ -from decimal import Decimal import unittest +from decimal import Decimal +from tuprolog.math import * -from tuprolog.core import big_integer, python_integer, big_decimal, python_decimal, BIG_INTEGER_ZERO, BIG_INTEGER_TEN, \ - BIG_INTEGER_ONE, BIG_INTEGER_NEGATIVE_ONE, BIG_INTEGER_TWO, BIG_DECIMAL_PI, BIG_DECIMAL_E, BIG_DECIMAL_ONE_TENTH, \ - BIG_DECIMAL_ONE_HALF, BIG_DECIMAL_ONE, BIG_DECIMAL_ZERO, BigInteger class TestKtMath(unittest.TestCase): diff --git a/test/core/test_operators.py b/test/core/test_operators.py index a25d781..4bec388 100644 --- a/test/core/test_operators.py +++ b/test/core/test_operators.py @@ -1,9 +1,9 @@ +import unittest import random import string -import unittest from tuprolog.core import * -from tuprolog.core.operators import DEFAULT_OPERATORS, EMPTY_OPERATORS, STANDARD_OPERATORS, XF, XFY, YF, YFX, FX, FY, \ - XFX, operator, operator_set, OperatorSet, specifier +from tuprolog.core.operators import * +import jpype.imports from java.lang import IllegalArgumentException # type: ignore diff --git a/test/core/test_terms.py b/test/core/test_terms.py index 53e5c63..e9b341e 100644 --- a/test/core/test_terms.py +++ b/test/core/test_terms.py @@ -1,5 +1,4 @@ import unittest -from tuprolog import * from tuprolog.core import * class TestTermCreation(unittest.TestCase): diff --git a/test/core/test_try_except.py b/test/core/test_try_except.py index 4e7d48a..9e000c8 100644 --- a/test/core/test_try_except.py +++ b/test/core/test_try_except.py @@ -1,6 +1,6 @@ import unittest -from tuprolog.core.exception import * from tuprolog.core import Substitution, Atom +from tuprolog.core.exception import * class TestExceptions(unittest.TestCase): diff --git a/test/core/test_unify.py b/test/core/test_unify.py index 61ec3a5..2d9ef82 100644 --- a/test/core/test_unify.py +++ b/test/core/test_unify.py @@ -1,7 +1,7 @@ import unittest +from tuprolog.jvmutils import Pair from tuprolog.core import scope from tuprolog.unify import DEFAULT_UNIFICATOR -from tuprolog.jvmutils import Pair class TestSubstitutionMerge(unittest.TestCase): def test_merge_with(self): diff --git a/test/core/test_visitors.py b/test/core/test_visitors.py index 354188d..2b32d6f 100644 --- a/test/core/test_visitors.py +++ b/test/core/test_visitors.py @@ -1,12 +1,12 @@ import unittest from tuprolog.core import Atom, Integer, Var -from tuprolog.core.visitors import AbstractTermVisitor +from tuprolog.core import AbstractTermVisitor import jpype.imports import kotlin.jvm.functions as _functions # type: ignore import unittest from tuprolog.core import * -from tuprolog.core.visitors import AbstractTermVisitor +from tuprolog.core import AbstractTermVisitor class TestVisitors(unittest.TestCase): diff --git a/test/post_install_test.py b/test/post_install_test.py index 9f0cf4c..2bc013e 100644 --- a/test/post_install_test.py +++ b/test/post_install_test.py @@ -1,6 +1,6 @@ from tuprolog.core import * from tuprolog.core.parsing import * -from tuprolog.core.visitors import AbstractTermVisitor +from tuprolog.core import AbstractTermVisitor formatter = TermFormatter.prettyExpressions() diff --git a/tuprolog/__main__.py b/tuprolog/__main__.py index e487d52..283e19c 100644 --- a/tuprolog/__main__.py +++ b/tuprolog/__main__.py @@ -2,7 +2,7 @@ from tuprolog.core import * from tuprolog.core.comparators import * from tuprolog.core.exception import * -from tuprolog.core.formatters import * +from tuprolog.core.impl import * from tuprolog.core.operators import * from tuprolog.core.visitors import * from tuprolog.core.parsing import * diff --git a/tuprolog/core/__init__.py b/tuprolog/core/__init__.py index 1ea9ece..ff10c46 100644 --- a/tuprolog/core/__init__.py +++ b/tuprolog/core/__init__.py @@ -1,206 +1,3 @@ -from typing import Iterable, Dict, Tuple as PyTuple, Union -from decimal import Decimal -from jpype import JImplements, JOverride -from tuprolog import logger -from tuprolog.pyutils import iterable_or_varargs -from tuprolog.jvmutils import jiterable, jmap -from ._ktadapt import * -from ._ktmath import * -import jpype.imports -import it.unibo.tuprolog.core as _core # type: ignore - - -Applicable = _core.Applicable - -Atom = _core.Atom - -Block = _core.Block - -Clause = _core.Clause - -Cons = _core.Cons - -Constant = _core.Constant - -Directive = _core.Directive - -Empty = _core.Empty - -EmptyBlock = _core.EmptyBlock - -EmptyList = _core.EmptyList - -Fact = _core.Fact - -Formatter = _core.Formatter - -Indicator = _core.Indicator - -Integer = _core.Integer - -List = _core.List - -Numeric = _core.Numeric - -Real = _core.Real - -Recursive = _core.Recursive - -Rule = _core.Rule - -Scope = _core.Scope - -Struct = _core.Struct - -Substitution = _core.Substitution - -Term = _core.Term - -TermComparator = _core.TermComparator - -TermConvertible = _core.TermConvertible - -TermFormatter = _core.TermFormatter - -Terms = _core.Terms - -TermVisitor = _core.TermVisitor - -Truth = _core.Truth - -Tuple = _core.Tuple - -Var = _core.Var - -Variabled = _core.Variabled - - -@JImplements(TermConvertible) -class AbstractTermConvertible(object): - @JOverride - def toTerm(self): - raise NotImplementedError() - - -def atom(string: str) -> Atom: - return Atom.of(string) - - -def block(*terms: Union[Term, Iterable[Term]]) -> Block: - return iterable_or_varargs(terms, lambda ts: Block.of(jiterable(ts))) - - -def clause(head: Term = None, *body: Union[Term, Iterable[Term]]): - return iterable_or_varargs(body, lambda bs: Clause.of(head, jiterable(bs))) - - -def empty_logic_list() -> EmptyList: - return EmptyList.getInstance() - - -def cons(head: Term, tail: Term = None) -> Cons: - if tail is None: - return Cons.singleton(head) - else: - return Cons.of(head, tail) - - -def directive(*goals: Union[Term, Iterable[Term]]) -> Directive: - return iterable_or_varargs(goals, lambda gs: Directive.of(jiterable(gs))) - - -def empty_block() -> Block: - return EmptyBlock.getInstance() - - -def fact(struct: Union[Term, Iterable[Term]]) -> Fact: - return Fact.of(struct) - - -def indicator(name: Union[str, Term], arity: Union[int, Term]) -> Indicator: - return Indicator.of(name, arity) - - -def integer(value: Union[int, BigInteger, str]) -> Integer: - return Integer.of(big_integer(value)) - - -def real(value: Union[float, BigDecimal, str, Decimal]) -> Real: - if isinstance(value, BigDecimal): - return Real.of(value) - return Real.of(big_decimal(value)) - - -def numeric(value: Union[int, BigInteger, BigDecimal, str, float, Decimal]) -> Numeric: - if isinstance(value, str): - return Numeric.of(jpype.JString @ value) - if isinstance(value, int) or isinstance(value, BigInteger): - return integer(value) - return real(value) - - -def rule(head: Struct, *body: Union[Term, Iterable[Term]]) -> Rule: - return iterable_or_varargs(body, lambda bs: Rule.of(head, jiterable(bs))) - - -def struct(functor: str, *args: Union[Term, Iterable[Term]]) -> Struct: - return iterable_or_varargs(args, lambda xs: Struct.of(functor, jiterable(xs))) - - -def truth(boolean: bool) -> Truth: - return Truth.of(boolean) - - -TRUE = Truth.TRUE - -FALSE = Truth.FALSE - -FAIL = Truth.FAIL - - -def logic_list(*items: Union[Term, Iterable[Term]]) -> List: - return iterable_or_varargs(items, lambda xs: List.of(jiterable(xs))) - - -def logic_list_from(items: Iterable[Term], last: Term = None) -> List: - return List.from_(jiterable(items), last) - - -def logic_tuple(first: Term, second: Term, *others: Union[Term, Iterable[Term]]) -> Tuple: - return iterable_or_varargs(others, lambda os: Tuple.of(jiterable([first, second] + list(os)))) - - -def var(name: str) -> Var: - return Var.of(name) - - -def unifier(assignments: Dict[Var, Term] = {}) -> Substitution.Unifier: - return Substitution.unifier(jmap(assignments)) - - -def substitution(assignments: Dict[Var, Term] = {}) -> Substitution: - return Substitution.of(jmap(assignments)) - - -def failed() -> Substitution.Fail: - return Substitution.failed() - - -EMPTY_UNIFIER: Substitution.Unifier = substitution() - -FAILED_SUBSTITUTION: Substitution.Fail = failed() - - -def scope(*variables: Union[Var, str]) -> Scope: - if len(variables) == 0: - return Scope.empty() - vars = [var(v) if isinstance(v, str) else v for v in variables] - return Scope.of(vars[0], jpype.JArray(Var) @ vars[1:]) - - -def variables(*names: str) -> PyTuple[Var]: - assert len(names) > 0 - return tuple((var(n) for n in names)) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.core.*") +import tuprolog.core._adapters as _ +from ._definitions import * +from ._api import * diff --git a/tuprolog/core/_ktadapt.py b/tuprolog/core/_adapters.py similarity index 97% rename from tuprolog/core/_ktadapt.py rename to tuprolog/core/_adapters.py index 87c1dd1..e4e377a 100644 --- a/tuprolog/core/_ktadapt.py +++ b/tuprolog/core/_adapters.py @@ -1,9 +1,9 @@ from typing import Sized, Callable -from jpype import JImplements, JOverride, JImplementationFor +from jpype import JOverride, JImplementationFor from tuprolog import logger from tuprolog.jvmutils import jiterable, kfunction from tuprolog.pyutils import iterable_or_varargs -from ._ktmath import big_integer, BigInteger, python_integer, python_decimal +from tuprolog.math import big_integer, BigInteger, python_integer, python_decimal @JImplementationFor("it.unibo.tuprolog.core.Term") diff --git a/tuprolog/core/_api.py b/tuprolog/core/_api.py new file mode 100644 index 0000000..f436cbb --- /dev/null +++ b/tuprolog/core/_api.py @@ -0,0 +1,121 @@ +from typing import Iterable, Dict, Tuple as PyTuple, Union +from decimal import Decimal +from tuprolog.pyutils import iterable_or_varargs +from tuprolog.jvmutils import jiterable, jmap +from tuprolog.math import big_integer, big_decimal, BigInteger, BigDecimal +from ._definitions import * + + +def atom(string: str) -> Atom: + return Atom.of(string) + + +def block(*terms: Union[Term, Iterable[Term]]) -> Block: + return iterable_or_varargs(terms, lambda ts: Block.of(jiterable(ts))) + + +def clause(head: Term = None, *body: Union[Term, Iterable[Term]]): + return iterable_or_varargs(body, lambda bs: Clause.of(head, jiterable(bs))) + + +def empty_logic_list() -> EmptyList: + return EmptyList.getInstance() + + +def cons(head: Term, tail: Term = None) -> Cons: + if tail is None: + return Cons.singleton(head) + else: + return Cons.of(head, tail) + + +def directive(*goals: Union[Term, Iterable[Term]]) -> Directive: + return iterable_or_varargs(goals, lambda gs: Directive.of(jiterable(gs))) + + +def empty_block() -> Block: + return EmptyBlock.getInstance() + + +def fact(struct: Union[Term, Iterable[Term]]) -> Fact: + return Fact.of(struct) + + +def indicator(name: Union[str, Term], arity: Union[int, Term]) -> Indicator: + return Indicator.of(name, arity) + + +def integer(value: Union[int, BigInteger, str]) -> Integer: + return Integer.of(big_integer(value)) + + +def real(value: Union[float, BigDecimal, str, Decimal]) -> Real: + if isinstance(value, BigDecimal): + return Real.of(value) + return Real.of(big_decimal(value)) + + +def numeric(value: Union[int, BigInteger, BigDecimal, str, float, Decimal]) -> Numeric: + if isinstance(value, str): + return Numeric.of(jpype.JString @ value) + if isinstance(value, int) or isinstance(value, BigInteger): + return integer(value) + return real(value) + + +def rule(head: Struct, *body: Union[Term, Iterable[Term]]) -> Rule: + return iterable_or_varargs(body, lambda bs: Rule.of(head, jiterable(bs))) + + +def struct(functor: str, *args: Union[Term, Iterable[Term]]) -> Struct: + return iterable_or_varargs(args, lambda xs: Struct.of(functor, jiterable(xs))) + + +def truth(boolean: bool) -> Truth: + return Truth.of(boolean) + + +def logic_list(*items: Union[Term, Iterable[Term]]) -> List: + return iterable_or_varargs(items, lambda xs: List.of(jiterable(xs))) + + +def logic_list_from(items: Iterable[Term], last: Term = None) -> List: + return List.from_(jiterable(items), last) + + +def logic_tuple(first: Term, second: Term, *others: Union[Term, Iterable[Term]]) -> Tuple: + return iterable_or_varargs(others, lambda os: Tuple.of(jiterable([first, second] + list(os)))) + + +def var(name: str) -> Var: + return Var.of(name) + + +def unifier(assignments: Dict[Var, Term] = {}) -> Substitution.Unifier: + return Substitution.unifier(jmap(assignments)) + + +def substitution(assignments: Dict[Var, Term] = {}) -> Substitution: + return Substitution.of(jmap(assignments)) + + +def failed() -> Substitution.Fail: + return Substitution.failed() + + +EMPTY_UNIFIER: Substitution.Unifier = substitution() + + +FAILED_SUBSTITUTION: Substitution.Fail = failed() + + +def scope(*variables: Union[Var, str]) -> Scope: + if len(variables) == 0: + return Scope.empty() + vars = [var(v) if isinstance(v, str) else v for v in variables] + return Scope.of(vars[0], jpype.JArray(Var) @ vars[1:]) + + +def variables(*names: str) -> PyTuple[Var]: + assert len(names) > 0 + return tuple((var(n) for n in names)) diff --git a/tuprolog/core/_definitions.py b/tuprolog/core/_definitions.py new file mode 100644 index 0000000..094dd65 --- /dev/null +++ b/tuprolog/core/_definitions.py @@ -0,0 +1,226 @@ +from jpype import JImplements, JOverride +from tuprolog import logger +import jpype.imports +import it.unibo.tuprolog.core as _core # type: ignore + + +Applicable = _core.Applicable + + +Atom = _core.Atom + + +Block = _core.Block + + +Clause = _core.Clause + + +Cons = _core.Cons + + +Constant = _core.Constant + + +Directive = _core.Directive + + +Empty = _core.Empty + + +EmptyBlock = _core.EmptyBlock + + +EmptyList = _core.EmptyList + + +Fact = _core.Fact + + +Formatter = _core.Formatter + + +Indicator = _core.Indicator + + +Integer = _core.Integer + + +List = _core.List + + +Numeric = _core.Numeric + + +Real = _core.Real + + +Recursive = _core.Recursive + + +Rule = _core.Rule + + +Scope = _core.Scope + + +Struct = _core.Struct + + +Substitution = _core.Substitution + + +Term = _core.Term + + +TermComparator = _core.TermComparator + + +TermConvertible = _core.TermConvertible + + +TermFormatter = _core.TermFormatter + + +Terms = _core.Terms + + +TermVisitor = _core.TermVisitor + + +Truth = _core.Truth + + +Tuple = _core.Tuple + + +Var = _core.Var + + +Variabled = _core.Variabled + + +TRUE = Truth.TRUE + + +FALSE = Truth.FALSE + + +FAIL = Truth.FAIL + + +@JImplements(TermComparator) +class AbstractTermComparator(object): + @JOverride + def equals(self, other): + return self is other + + @JOverride + def compare(self, first, second): + raise NotImplementedError() + + +@JImplements(TermConvertible) +class AbstractTermConvertible(object): + @JOverride + def toTerm(self): + raise NotImplementedError() + + +@JImplements(TermVisitor) +class AbstractTermVisitor(object): + + @JOverride + def defaultValue(self, term): + raise NotImplementedError() + + @JOverride + def visitTerm(self, term): + return TermVisitor.visitTerm(self, term) + + @JOverride + def visitVar(self, term): + return TermVisitor.visitVar(self, term) + + @JOverride + def visitConstant(self, term): + return TermVisitor.visitConstant(self, term) + + @JOverride + def visitStruct(self, term): + return TermVisitor.visitStruct(self, term) + + @JOverride + def visitCollection(self, term): + return TermVisitor.visitCollection(self, term) + + @JOverride + def visitAtom(self, term): + return TermVisitor.visitAtom(self, term) + + @JOverride + def visitTruth(self, term): + return TermVisitor.visitTruth(self, term) + + @JOverride + def visitNumeric(self, term): + return TermVisitor.visitNumeric(self, term) + + @JOverride + def visitInteger(self, term): + return TermVisitor.visitInteger(self, term) + + @JOverride + def visitReal(self, term): + return TermVisitor.visitReal(self, term) + + @JOverride + def visitBlock(self, term): + return TermVisitor.visitBlock(self, term) + + @JOverride + def visitEmpty(self, term): + return TermVisitor.visitEmpty(self, term) + + @JOverride + def visitEmptyBlock(self, term): + return TermVisitor.visitEmptyBlock(self, term) + + @JOverride + def visitList(self, term): + return TermVisitor.visitList(self, term) + + @JOverride + def visitCons(self, term): + return TermVisitor.visitCons(self, term) + + @JOverride + def visitEmptyList(self, term): + return TermVisitor.visitEmptyList(self, term) + + @JOverride + def visitTuple(self, term): + return TermVisitor.visitTuple(self, term) + + @JOverride + def visitIndicator(self, term): + return TermVisitor.visitIndicator(self, term) + + @JOverride + def visitClause(self, term): + return TermVisitor.visitClause(self, term) + + @JOverride + def visitRule(self, term): + return TermVisitor.visitRule(self, term) + + @JOverride + def visitFact(self, term): + return TermVisitor.visitFact(self, term) + + @JOverride + def visitDirective(self, term): + return TermVisitor.visitDirective(self, term) + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.core.*") diff --git a/tuprolog/core/comparators.py b/tuprolog/core/comparators.py deleted file mode 100644 index 22664ad..0000000 --- a/tuprolog/core/comparators.py +++ /dev/null @@ -1,16 +0,0 @@ -from jpype import JImplements, JOverride -from tuprolog import logger -from tuprolog.core import TermComparator - -@JImplements(TermComparator) -class AbstractTermComparator(object): - @JOverride - def equals(self, other): - return self is other - - @JOverride - def compare(self, first, second): - raise NotImplementedError() - - -logger.debug("Loaded compatibility layer for JVM subtypes of " + str(TermComparator.class_.getName())) diff --git a/tuprolog/core/formatters.py b/tuprolog/core/impl.py similarity index 100% rename from tuprolog/core/formatters.py rename to tuprolog/core/impl.py diff --git a/tuprolog/core/visitors.py b/tuprolog/core/visitors.py index 312d1bf..e5580f1 100644 --- a/tuprolog/core/visitors.py +++ b/tuprolog/core/visitors.py @@ -3,102 +3,7 @@ import jpype.imports import it.unibo.tuprolog.core as _core # type: ignore -TermVisitor = _core.TermVisitor -@JImplements(TermVisitor) -class AbstractTermVisitor(object): - - @JOverride - def defaultValue(self, term): - raise NotImplementedError() - - @JOverride - def visitTerm(self, term): - return TermVisitor.visitTerm(self, term) - - @JOverride - def visitVar(self, term): - return TermVisitor.visitVar(self, term) - - @JOverride - def visitConstant(self, term): - return TermVisitor.visitConstant(self, term) - - @JOverride - def visitStruct(self, term): - return TermVisitor.visitStruct(self, term) - - @JOverride - def visitCollection(self, term): - return TermVisitor.visitCollection(self, term) - - @JOverride - def visitAtom(self, term): - return TermVisitor.visitAtom(self, term) - - @JOverride - def visitTruth(self, term): - return TermVisitor.visitTruth(self, term) - - @JOverride - def visitNumeric(self, term): - return TermVisitor.visitNumeric(self, term) - - @JOverride - def visitInteger(self, term): - return TermVisitor.visitInteger(self, term) - - @JOverride - def visitReal(self, term): - return TermVisitor.visitReal(self, term) - - @JOverride - def visitBlock(self, term): - return TermVisitor.visitBlock(self, term) - - @JOverride - def visitEmpty(self, term): - return TermVisitor.visitEmpty(self, term) - - @JOverride - def visitEmptyBlock(self, term): - return TermVisitor.visitEmptyBlock(self, term) - - @JOverride - def visitList(self, term): - return TermVisitor.visitList(self, term) - - @JOverride - def visitCons(self, term): - return TermVisitor.visitCons(self, term) - - @JOverride - def visitEmptyList(self, term): - return TermVisitor.visitEmptyList(self, term) - - @JOverride - def visitTuple(self, term): - return TermVisitor.visitTuple(self, term) - - @JOverride - def visitIndicator(self, term): - return TermVisitor.visitIndicator(self, term) - - @JOverride - def visitClause(self, term): - return TermVisitor.visitClause(self, term) - - @JOverride - def visitRule(self, term): - return TermVisitor.visitRule(self, term) - - @JOverride - def visitFact(self, term): - return TermVisitor.visitFact(self, term) - - @JOverride - def visitDirective(self, term): - return TermVisitor.visitDirective(self, term) logger.debug("Loaded compatibility layer for JVM subtypes of " + str(TermVisitor.class_.getName())) diff --git a/tuprolog/libs/__init__.py b/tuprolog/libs/__init__.py index 3ebd2fc..5505c02 100644 --- a/tuprolog/libs/__init__.py +++ b/tuprolog/libs/__init__.py @@ -1,23 +1 @@ -import os -import jdk -import shutil -import logging -from pathlib import Path - -JAVA_HOME = Path(__file__).parent / 'java' - -CLASSPATH = Path(__file__).parent - -logger = logging.getLogger('tuprolog') - -def install_java_if_missing() -> Path: - if JAVA_HOME.exists(): - return - java_version = os.getenv('JAVA_VERSION', '11') - destination_folder = str(CLASSPATH) - logger.info(f'Downloading Java {java_version} in {destination_folder}') - installation_path = Path(jdk.install(java_version, jre=not java_version.startswith('16'), path=destination_folder)) # Java 16 doesn't have a JRE - destination_folder = JAVA_HOME - logger.info(f'Installing Java {java_version} in {destination_folder}') - shutil.copytree(installation_path, destination_folder, dirs_exist_ok=True) - shutil.rmtree(installation_path, ignore_errors=True) +from .java import JAVA_HOME, CLASSPATH, install_java_if_missing diff --git a/tuprolog/libs/java.py b/tuprolog/libs/java.py new file mode 100644 index 0000000..3ebd2fc --- /dev/null +++ b/tuprolog/libs/java.py @@ -0,0 +1,23 @@ +import os +import jdk +import shutil +import logging +from pathlib import Path + +JAVA_HOME = Path(__file__).parent / 'java' + +CLASSPATH = Path(__file__).parent + +logger = logging.getLogger('tuprolog') + +def install_java_if_missing() -> Path: + if JAVA_HOME.exists(): + return + java_version = os.getenv('JAVA_VERSION', '11') + destination_folder = str(CLASSPATH) + logger.info(f'Downloading Java {java_version} in {destination_folder}') + installation_path = Path(jdk.install(java_version, jre=not java_version.startswith('16'), path=destination_folder)) # Java 16 doesn't have a JRE + destination_folder = JAVA_HOME + logger.info(f'Installing Java {java_version} in {destination_folder}') + shutil.copytree(installation_path, destination_folder, dirs_exist_ok=True) + shutil.rmtree(installation_path, ignore_errors=True) diff --git a/tuprolog/math/__init__.py b/tuprolog/math/__init__.py new file mode 100644 index 0000000..3272497 --- /dev/null +++ b/tuprolog/math/__init__.py @@ -0,0 +1,2 @@ +from ._definitions import * +from ._api import * diff --git a/tuprolog/core/_ktmath.py b/tuprolog/math/_api.py similarity index 70% rename from tuprolog/core/_ktmath.py rename to tuprolog/math/_api.py index a2b195c..a66b4f8 100644 --- a/tuprolog/core/_ktmath.py +++ b/tuprolog/math/_api.py @@ -1,48 +1,8 @@ from typing import Union import decimal -import jpype.imports -import org.gciatto.kt.math as _ktmath # type: ignore -import java.lang as _java_lang # type: ignore - from tuprolog.pyutils import and_then - -BigInteger = _ktmath.BigInteger - -BigDecimal = _ktmath.BigDecimal - -MathContext = _ktmath.MathContext - -RoundingMode = _ktmath.RoundingMode - -_MAX_LONG = _java_lang.Long.MAX_VALUE - -_MIN_LONG = _java_lang.Long.MIN_VALUE - -BIG_INTEGER_MAX_LONG = BigInteger.of(_MAX_LONG) - -BIG_INTEGER_MIN_LONG = BigInteger.of(_MIN_LONG) - -BIG_INTEGER_ZERO = BigInteger.ZERO - -BIG_INTEGER_TEN = BigInteger.TEN - -BIG_INTEGER_ONE = BigInteger.ONE - -BIG_INTEGER_NEGATIVE_ONE = BigInteger.NEGATIVE_ONE - -BIG_INTEGER_TWO = BigInteger.TWO - -BIG_DECIMAL_ZERO = BigDecimal.ZERO - -BIG_DECIMAL_ONE = BigDecimal.ONE - -BIG_DECIMAL_ONE_HALF = BigDecimal.ONE_HALF - -BIG_DECIMAL_ONE_TENTH = BigDecimal.ONE_TENTH - -BIG_DECIMAL_E = BigDecimal.E - -BIG_DECIMAL_PI = BigDecimal.PI +from ._definitions import BigInteger, BigDecimal, MathContext, RoundingMode +from jpype import JDouble, JString def big_integer(value: Union[str, int], radix: int = None) -> BigInteger: @@ -50,7 +10,7 @@ def big_integer(value: Union[str, int], radix: int = None) -> BigInteger: assert isinstance(value, str) return BigInteger.of(value, radix) if isinstance(value, str): - return BigInteger.of(jpype.JString @ value) + return BigInteger.of(JString @ value) assert isinstance(value, int) return BigInteger.of(str(value)) @@ -99,13 +59,13 @@ def big_decimal(value: Union[str, int, float, decimal.Decimal], precision=0, if isinstance(value, str): return BigDecimal.of(value, context) if isinstance(value, decimal.Decimal): - return BigDecimal.of(jpype.JString @ str(value), context) + return BigDecimal.of(JString @ str(value), context) if isinstance(value, BigInteger): return BigDecimal.of(value, context) if isinstance(value, int): return BigDecimal.of(big_integer(value), context) assert isinstance(value, float) - return BigDecimal.of(jpype.JDouble @ value, context) + return BigDecimal.of(JDouble @ value, context) def python_decimal(value: BigDecimal) -> decimal.Decimal: diff --git a/tuprolog/math/_definitions.py b/tuprolog/math/_definitions.py new file mode 100644 index 0000000..27d2899 --- /dev/null +++ b/tuprolog/math/_definitions.py @@ -0,0 +1,60 @@ +import jpype.imports +import org.gciatto.kt.math as _ktmath # type: ignore +import java.lang as _java_lang # type: ignore + + +BigInteger = _ktmath.BigInteger + + +BigDecimal = _ktmath.BigDecimal + + +MathContext = _ktmath.MathContext + + +RoundingMode = _ktmath.RoundingMode + + +_MAX_LONG = _java_lang.Long.MAX_VALUE + + +_MIN_LONG = _java_lang.Long.MIN_VALUE + + +BIG_INTEGER_MAX_LONG = BigInteger.of(_MAX_LONG) + + +BIG_INTEGER_MIN_LONG = BigInteger.of(_MIN_LONG) + + +BIG_INTEGER_ZERO = BigInteger.ZERO + + +BIG_INTEGER_TEN = BigInteger.TEN + + +BIG_INTEGER_ONE = BigInteger.ONE + + +BIG_INTEGER_NEGATIVE_ONE = BigInteger.NEGATIVE_ONE + + +BIG_INTEGER_TWO = BigInteger.TWO + + +BIG_DECIMAL_ZERO = BigDecimal.ZERO + + +BIG_DECIMAL_ONE = BigDecimal.ONE + + +BIG_DECIMAL_ONE_HALF = BigDecimal.ONE_HALF + + +BIG_DECIMAL_ONE_TENTH = BigDecimal.ONE_TENTH + + +BIG_DECIMAL_E = BigDecimal.E + + +BIG_DECIMAL_PI = BigDecimal.PI From c93a8b3da7e7b4715c4ce24f7462143fd5b004f0 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 9 Oct 2023 18:52:29 +0200 Subject: [PATCH 124/154] Re-organize unify --- tuprolog/unify/__init__.py | 49 +------------------ tuprolog/unify/_api.py | 36 ++++++++++++++ tuprolog/unify/_definitions.py | 12 +++++ .../{exception/__init__.py => exception.py} | 0 4 files changed, 50 insertions(+), 47 deletions(-) create mode 100644 tuprolog/unify/_api.py create mode 100644 tuprolog/unify/_definitions.py rename tuprolog/unify/{exception/__init__.py => exception.py} (100%) diff --git a/tuprolog/unify/__init__.py b/tuprolog/unify/__init__.py index 65d22ac..3272497 100644 --- a/tuprolog/unify/__init__.py +++ b/tuprolog/unify/__init__.py @@ -1,47 +1,2 @@ -from tuprolog import logger -from tuprolog.core import Term, Substitution -import jpype.imports -import it.unibo.tuprolog.unify as _unify # type: ignore - - -Unificator = _unify.Unificator - - -def strict_unificator(context: Substitution = None) -> Unificator: - if context is None: - return Unificator.strict() - else: - return Unificator.strict(context) - - -def naive_unificator(context: Substitution = None) -> Unificator: - if context is None: - return Unificator.naive() - else: - return Unificator.naive(context) - - -def cached_unificator(unificator: Unificator, cache_size: int = Unificator.DEFAULT_CACHE_CAPACITY) -> Unificator: - return Unificator.cached(unificator, cache_size) - - -def unificator(context: Substitution = None) -> Unificator: - return cached_unificator(strict_unificator(context)) - - -DEFAULT_UNIFICATOR = Unificator.getDefault() - - -def mgu(x: Term, y: Term, occur_check: bool = True) -> Substitution: - return DEFAULT_UNIFICATOR.mgu(x, y, occur_check) - - -def unify(x: Term, y: Term, occur_check: bool = True) -> Term: - return DEFAULT_UNIFICATOR.unify(x, y, occur_check) - - -def match(x: Term, y: Term, occur_check: bool = True) -> bool: - return DEFAULT_UNIFICATOR.match(x, y, occur_check) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.unify.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/unify/_api.py b/tuprolog/unify/_api.py new file mode 100644 index 0000000..344422c --- /dev/null +++ b/tuprolog/unify/_api.py @@ -0,0 +1,36 @@ +from tuprolog.core import Term, Substitution +from ._definitions import * + + +def strict_unificator(context: Substitution = None) -> Unificator: + if context is None: + return Unificator.strict() + else: + return Unificator.strict(context) + + +def naive_unificator(context: Substitution = None) -> Unificator: + if context is None: + return Unificator.naive() + else: + return Unificator.naive(context) + + +def cached_unificator(unificator: Unificator, cache_size: int = Unificator.DEFAULT_CACHE_CAPACITY) -> Unificator: + return Unificator.cached(unificator, cache_size) + + +def unificator(context: Substitution = None) -> Unificator: + return cached_unificator(strict_unificator(context)) + + +def mgu(x: Term, y: Term, occur_check: bool = True) -> Substitution: + return DEFAULT_UNIFICATOR.mgu(x, y, occur_check) + + +def unify(x: Term, y: Term, occur_check: bool = True) -> Term: + return DEFAULT_UNIFICATOR.unify(x, y, occur_check) + + +def match(x: Term, y: Term, occur_check: bool = True) -> bool: + return DEFAULT_UNIFICATOR.match(x, y, occur_check) diff --git a/tuprolog/unify/_definitions.py b/tuprolog/unify/_definitions.py new file mode 100644 index 0000000..4fbbb0b --- /dev/null +++ b/tuprolog/unify/_definitions.py @@ -0,0 +1,12 @@ +from tuprolog import logger +import jpype.imports +import it.unibo.tuprolog.unify as _unify # type: ignore + + +Unificator = _unify.Unificator + + +DEFAULT_UNIFICATOR = Unificator.getDefault() + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.unify.*") diff --git a/tuprolog/unify/exception/__init__.py b/tuprolog/unify/exception.py similarity index 100% rename from tuprolog/unify/exception/__init__.py rename to tuprolog/unify/exception.py From 0ae0c37bd6ec52deac6efba327310383aa93528b Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 9 Oct 2023 19:13:24 +0200 Subject: [PATCH 125/154] Reorganize theory module --- tuprolog/theory/__init__.py | 27 +++---------------- tuprolog/theory/{_ktadapt.py => _adapters.py} | 0 tuprolog/theory/_api.py | 14 ++++++++++ tuprolog/theory/_definitions.py | 11 ++++++++ 4 files changed, 28 insertions(+), 24 deletions(-) rename tuprolog/theory/{_ktadapt.py => _adapters.py} (100%) create mode 100644 tuprolog/theory/_api.py create mode 100644 tuprolog/theory/_definitions.py diff --git a/tuprolog/theory/__init__.py b/tuprolog/theory/__init__.py index 59ac08b..ddab90b 100644 --- a/tuprolog/theory/__init__.py +++ b/tuprolog/theory/__init__.py @@ -1,24 +1,3 @@ -from typing import Iterable, Union -from tuprolog import logger -from tuprolog.core import Clause -from tuprolog.unify import Unificator -from ._ktadapt import * -import jpype.imports -import it.unibo.tuprolog.theory as _theory # type: ignore - -Theory = _theory.Theory - -MutableTheory = _theory.MutableTheory - -RetractResult = _theory.RetractResult - - -def theory(*clauses: Union[Clause, Iterable[Clause]]) -> Theory: - return iterable_or_varargs(clauses, lambda ts: Theory.of(jiterable(ts))) - - -def mutable_theory(*clauses: Union[Clause, Iterable[Clause]]) -> MutableTheory: - return iterable_or_varargs(clauses, lambda ts: MutableTheory.of(Unificator.getDefault(), jiterable(ts))) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.theory.*") +import tuprolog.theory._adapters as _ +from ._definitions import * +from ._api import * diff --git a/tuprolog/theory/_ktadapt.py b/tuprolog/theory/_adapters.py similarity index 100% rename from tuprolog/theory/_ktadapt.py rename to tuprolog/theory/_adapters.py diff --git a/tuprolog/theory/_api.py b/tuprolog/theory/_api.py new file mode 100644 index 0000000..f79896e --- /dev/null +++ b/tuprolog/theory/_api.py @@ -0,0 +1,14 @@ +from typing import Iterable, Union +from tuprolog.core import Clause +from tuprolog.unify import Unificator +from tuprolog.jvmutils import jiterable +from tuprolog.pyutils import iterable_or_varargs +from ._definitions import * + + +def theory(*clauses: Union[Clause, Iterable[Clause]]) -> Theory: + return iterable_or_varargs(clauses, lambda ts: Theory.of(jiterable(ts))) + + +def mutable_theory(*clauses: Union[Clause, Iterable[Clause]]) -> MutableTheory: + return iterable_or_varargs(clauses, lambda ts: MutableTheory.of(Unificator.getDefault(), jiterable(ts))) diff --git a/tuprolog/theory/_definitions.py b/tuprolog/theory/_definitions.py new file mode 100644 index 0000000..cffc997 --- /dev/null +++ b/tuprolog/theory/_definitions.py @@ -0,0 +1,11 @@ +from tuprolog import logger +import jpype.imports +import it.unibo.tuprolog.theory as _theory # type: ignore + +Theory = _theory.Theory + +MutableTheory = _theory.MutableTheory + +RetractResult = _theory.RetractResult + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.theory.*") From 1346eeb51ac55825c5194b6863243f3db375ec8f Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 9 Oct 2023 19:17:26 +0200 Subject: [PATCH 126/154] Move unify tests to unify --- test/unify/__init__.py | 0 test/{core => unify}/test_unify.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 test/unify/__init__.py rename test/{core => unify}/test_unify.py (93%) diff --git a/test/unify/__init__.py b/test/unify/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/core/test_unify.py b/test/unify/test_unify.py similarity index 93% rename from test/core/test_unify.py rename to test/unify/test_unify.py index 2d9ef82..3b2faea 100644 --- a/test/core/test_unify.py +++ b/test/unify/test_unify.py @@ -13,7 +13,7 @@ def test_merge_with(self): a = s.atom_of("a") for v_name, v in s.variables.items(): - assignment = s.unifier_of(Pair(v_name, a)) + assignment = s.unifier_of(Pair @ (v_name, a)) self.assertEqual( s.unifier_of( ("X", a), From 9475520ab637275d983a061244cd139463c2381e Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 9 Oct 2023 23:19:22 +0200 Subject: [PATCH 127/154] Remove star import --- tuprolog/core/_api.py | 7 ++++--- tuprolog/core/visitors.py | 9 --------- 2 files changed, 4 insertions(+), 12 deletions(-) delete mode 100644 tuprolog/core/visitors.py diff --git a/tuprolog/core/_api.py b/tuprolog/core/_api.py index f436cbb..48b6521 100644 --- a/tuprolog/core/_api.py +++ b/tuprolog/core/_api.py @@ -1,9 +1,10 @@ from typing import Iterable, Dict, Tuple as PyTuple, Union from decimal import Decimal +from jpype import JString, JArray from tuprolog.pyutils import iterable_or_varargs from tuprolog.jvmutils import jiterable, jmap from tuprolog.math import big_integer, big_decimal, BigInteger, BigDecimal -from ._definitions import * +from ._definitions import Atom, Block, Clause, Cons, Directive, EmptyBlock, EmptyList, Fact, Indicator, Integer, List, Numeric, Real, Rule, Scope, Struct, Substitution, Term, Tuple, Truth, Var def atom(string: str) -> Atom: @@ -57,7 +58,7 @@ def real(value: Union[float, BigDecimal, str, Decimal]) -> Real: def numeric(value: Union[int, BigInteger, BigDecimal, str, float, Decimal]) -> Numeric: if isinstance(value, str): - return Numeric.of(jpype.JString @ value) + return Numeric.of(JString @ value) if isinstance(value, int) or isinstance(value, BigInteger): return integer(value) return real(value) @@ -113,7 +114,7 @@ def scope(*variables: Union[Var, str]) -> Scope: if len(variables) == 0: return Scope.empty() vars = [var(v) if isinstance(v, str) else v for v in variables] - return Scope.of(vars[0], jpype.JArray(Var) @ vars[1:]) + return Scope.of(vars[0], JArray(Var) @ vars[1:]) def variables(*names: str) -> PyTuple[Var]: diff --git a/tuprolog/core/visitors.py b/tuprolog/core/visitors.py deleted file mode 100644 index e5580f1..0000000 --- a/tuprolog/core/visitors.py +++ /dev/null @@ -1,9 +0,0 @@ -from jpype import JImplements, JOverride -from tuprolog import logger -import jpype.imports -import it.unibo.tuprolog.core as _core # type: ignore - - - - -logger.debug("Loaded compatibility layer for JVM subtypes of " + str(TermVisitor.class_.getName())) From 7a0b8010cce24f6850c07c7bd21804ca22d48289 Mon Sep 17 00:00:00 2001 From: Luca Deluigi Date: Tue, 10 Oct 2023 09:54:56 +0200 Subject: [PATCH 128/154] Add unificator tests --- test/theory/test_theory.py | 43 ++++++++++++++++++++++++++++++++++ tuprolog/utils/__init__.py | 10 +------- tuprolog/utils/_definitions.py | 9 +++++++ 3 files changed, 53 insertions(+), 9 deletions(-) create mode 100644 test/theory/test_theory.py create mode 100644 tuprolog/utils/_definitions.py diff --git a/test/theory/test_theory.py b/test/theory/test_theory.py new file mode 100644 index 0000000..9961744 --- /dev/null +++ b/test/theory/test_theory.py @@ -0,0 +1,43 @@ +import unittest +from tuprolog.core import clause, var, struct, atom +from tuprolog.jvmutils import Iterable +from tuprolog.theory import theory + +class TestTheory(unittest.TestCase): + def test_empty_theory(self): + t = theory() + self.assertIsNotNone(t) + self.assertEqual(0, len(t)) + self.assertTrue(t.is_empty) + + def test_retract(self): + A = var('A') + a = atom('a') + f = lambda arg: struct('f', arg) + g = lambda arg: struct('g', arg) + t = theory([ + c1 := clause(f(A), g(A)), + clause(g(a)), + ]) + self.assertEqual(2, len(t)) + result = t.retract(c1) + self.assertEqual(1, len(result.theory)) + + def test_unificator(self): + A = var('A') + a = atom('a') + f = lambda arg: struct('f', arg) + g = lambda arg: struct('g', arg) + + t = theory([ + clause(g(a)), + ]) + results = list(t[f(a)]) + self.assertEqual(0, len(results)) + + t = theory([ + clause(f(A), g(A)), + clause(g(a)), + ]) + results = list(t[f(a)]) + self.assertEqual(1, len(results)) diff --git a/tuprolog/utils/__init__.py b/tuprolog/utils/__init__.py index 2085d89..2126cab 100644 --- a/tuprolog/utils/__init__.py +++ b/tuprolog/utils/__init__.py @@ -1,9 +1 @@ -from tuprolog import logger -import jpype.imports -import it.unibo.tuprolog.utils as _utils # type: ignore - -Castable = _utils.Castable - -Taggable = _utils.Taggable - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.utils.*") +from ._definitions import Castable, Taggable diff --git a/tuprolog/utils/_definitions.py b/tuprolog/utils/_definitions.py new file mode 100644 index 0000000..2085d89 --- /dev/null +++ b/tuprolog/utils/_definitions.py @@ -0,0 +1,9 @@ +from tuprolog import logger +import jpype.imports +import it.unibo.tuprolog.utils as _utils # type: ignore + +Castable = _utils.Castable + +Taggable = _utils.Taggable + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.utils.*") From da00be955d9b3266e45571df8bee12ef404c8a17 Mon Sep 17 00:00:00 2001 From: Luca Deluigi Date: Tue, 10 Oct 2023 13:50:47 +0200 Subject: [PATCH 129/154] Fix all flake8 warning and make them errors --- .flake8 | 2 +- .github/workflows/ci.yml | 5 +--- setup.py | 24 ++++++++++++----- test/api/test_prolog.py | 13 ++++----- test/core/test_formatters.py | 6 +---- test/core/test_kt_math.py | 10 +++---- test/core/test_operators.py | 14 +++++----- test/core/test_parsing.py | 2 +- test/core/test_scope.py | 3 --- test/core/test_substitution.py | 4 +-- test/core/test_terms.py | 9 +++---- test/core/test_try_except.py | 8 ++---- test/core/test_visitors.py | 10 ------- test/post_install_test.py | 7 +---- test/solve/problog/test_problog_example.py | 7 ++--- test/theory/test_theory.py | 19 +++++++++---- test/unify/test_unify.py | 1 + tuprolog/__init__.py | 4 +-- tuprolog/core/_api.py | 4 ++- tuprolog/core/_definitions.py | 4 +-- tuprolog/core/exception.py | 4 +-- tuprolog/core/impl.py | 4 +-- tuprolog/core/operators/__init__.py | 4 +-- tuprolog/core/parsing/__init__.py | 6 ++--- tuprolog/jvmioutils.py | 10 +++---- tuprolog/jvmutils.py | 21 ++++++++------- tuprolog/libs/java.py | 12 ++++++++- tuprolog/math/_definitions.py | 6 ++--- tuprolog/solve/__init__.py | 4 +-- tuprolog/solve/channel/__init__.py | 6 ++--- tuprolog/solve/classic/__init__.py | 3 ++- tuprolog/solve/data/__init__.py | 4 +-- tuprolog/solve/exception/__init__.py | 4 +-- .../solve/exception/error/domain/__init__.py | 4 +-- .../exception/error/evaluation/__init__.py | 4 +-- .../exception/error/existence/__init__.py | 4 +-- .../exception/error/instantiation/__init__.py | 4 +-- .../solve/exception/error/message/__init__.py | 4 +-- .../exception/error/permission/__init__.py | 4 +-- .../error/representation/__init__.py | 4 +-- .../solve/exception/error/syntax/__init__.py | 4 +-- .../solve/exception/error/system/__init__.py | 6 ++--- .../solve/exception/error/type/__init__.py | 27 +++++++++++++++++-- tuprolog/solve/exception/warning/__init__.py | 4 +-- tuprolog/solve/flags/__init__.py | 4 +-- tuprolog/solve/function/__init__.py | 4 +-- tuprolog/solve/library/__init__.py | 6 ++--- tuprolog/solve/library/exception/__init__.py | 4 +-- tuprolog/solve/plp/__init__.py | 4 +-- tuprolog/solve/primitive/__init__.py | 4 +-- tuprolog/solve/problog/operators.py | 4 +-- tuprolog/solve/sideffcts/__init__.py | 4 +-- tuprolog/solve/stdlib/__init__.py | 4 +-- tuprolog/solve/stdlib/function/__init__.py | 4 +-- tuprolog/solve/stdlib/primitive/__init__.py | 4 +-- tuprolog/solve/stdlib/rule/__init__.py | 4 +-- tuprolog/theory/_api.py | 2 +- tuprolog/theory/_definitions.py | 4 +-- tuprolog/theory/parsing/__init__.py | 6 ++--- tuprolog/theory/parsing/_ktadapt.py | 1 - tuprolog/unify/_api.py | 2 +- tuprolog/unify/_definitions.py | 4 +-- tuprolog/unify/exception.py | 4 +-- tuprolog/utils/_definitions.py | 4 +-- 64 files changed, 205 insertions(+), 185 deletions(-) diff --git a/.flake8 b/.flake8 index 9866967..d9de4ec 100644 --- a/.flake8 +++ b/.flake8 @@ -1,5 +1,5 @@ [flake8] per-file-ignores = - __init__.py:F401, E402 + __init__.py:F401, F403 __main__.py:F401, F403 max-line-length = 127 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b40916c..1130e93 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,14 +97,11 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install ruff pytest if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Lint with Flake8 run: | # stop the build if there are Python syntax errors or undefined names - python -m flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - python -m flake8 . --count --exit-zero --statistics + python -m flake8 . --count --statistics install: strategy: diff --git a/setup.py b/setup.py index ee06421..7e2db32 100644 --- a/setup.py +++ b/setup.py @@ -19,11 +19,11 @@ def is_windows(): def run_maven(*args, cwd=None) -> (str, str): proc = subprocess.Popen( - MAVEN_EXECUTABLE + list(args), - shell=is_windows(), - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True, + MAVEN_EXECUTABLE + list(args), + shell=is_windows(), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, cwd=cwd) stdout, stderr = proc.communicate() if proc.returncode != 0: @@ -35,8 +35,17 @@ def download_jars(): stdout, _ = run_maven('-v') if 'Apache Maven' not in stdout: raise RuntimeError(f'Could not find Apache Maven in {stdout}') - run_maven('dependency:copy-dependencies', f'-DoutputDirectory={JAR_FOLDER}', cwd=Path(__file__).parent) - # run_maven('dependency:copy-dependencies', f'-DoutputDirectory={JAR_FOLDER}', '-Dclassifier=javadoc', cwd=Path(__file__).parent) + run_maven( + 'dependency:copy-dependencies', + f'-DoutputDirectory={JAR_FOLDER}', + cwd=Path(__file__).parent + ) + # run_maven( + # 'dependency:copy-dependencies', + # f'-DoutputDirectory={JAR_FOLDER}', + # '-Dclassifier=javadoc', + # cwd=Path(__file__).parent + # ) class BuildPyCommand(build_py): @@ -48,6 +57,7 @@ def run(self): class InstallCommand(install): def run(self): install.run(self) + def _post_install(): spec = importlib.util.spec_from_file_location(PACKAGE_NAME, JAR_FOLDER / '__init__.py') lib = importlib.util.module_from_spec(spec) diff --git a/test/api/test_prolog.py b/test/api/test_prolog.py index 6444d90..83a00ee 100644 --- a/test/api/test_prolog.py +++ b/test/api/test_prolog.py @@ -1,21 +1,22 @@ import unittest from tuprolog.core import rule, struct, var, fact, atom -from tuprolog.solve import * + class TestPrologWithResolution(unittest.TestCase): def test_abraham_family_tree(self): program = [ rule( - struct("ancestor", var("X"), var("Y")), # :- - struct("parent", var("X"), var("Y")) + struct("ancestor", var("X"), var("Y")), # :- + struct("parent", var("X"), var("Y")), ), rule( - struct("ancestor", var("X"), var("Y")), # :- - struct("parent", var("X"), var("Z")), - struct("ancestor", var("Z"), var("Y")) + struct("ancestor", var("X"), var("Y")), # :- + struct("parent", var("X"), var("Z")), + struct("ancestor", var("Z"), var("Y")), ), fact(struct("parent", atom("abraham"), atom("isaac"))), fact(struct("parent", atom("isaac"), atom("jacob"))), fact(struct("parent", atom("jacob"), atom("joseph"))), ] + print(program) # TODO: solve diff --git a/test/core/test_formatters.py b/test/core/test_formatters.py index 4307248..4e585ec 100644 --- a/test/core/test_formatters.py +++ b/test/core/test_formatters.py @@ -1,5 +1,5 @@ import unittest -from tuprolog.core import * +from tuprolog.core import Atom, Integer, Var from tuprolog.core.impl import DefaultTermFormatter @@ -9,7 +9,3 @@ def test_term_formatter(self): formatter = DefaultTermFormatter() for term in [Atom.of('a'), Integer.of(1), Var.of("X")]: self.assertEqual(formatter.format(term), str(term)) - - -if __name__ == '__main__': - unittest.main() diff --git a/test/core/test_kt_math.py b/test/core/test_kt_math.py index 721efff..694251d 100644 --- a/test/core/test_kt_math.py +++ b/test/core/test_kt_math.py @@ -1,7 +1,9 @@ import unittest from decimal import Decimal -from tuprolog.math import * - +from tuprolog.math import big_integer, python_integer, BigInteger, big_decimal, python_decimal +from tuprolog.math import BIG_INTEGER_ZERO, BIG_INTEGER_TEN, BIG_INTEGER_ONE, BIG_INTEGER_NEGATIVE_ONE, BIG_INTEGER_TWO +from tuprolog.math import BIG_DECIMAL_ZERO, BIG_DECIMAL_ONE, BIG_DECIMAL_ONE_HALF, BIG_DECIMAL_ONE_TENTH +from tuprolog.math import BIG_DECIMAL_E, BIG_DECIMAL_PI class TestKtMath(unittest.TestCase): @@ -179,7 +181,3 @@ def test_constants(self): self.assertEqual(big_decimal("0.1"), BIG_DECIMAL_ONE_TENTH) self.assertEqual(big_decimal(self.e), BIG_DECIMAL_E) self.assertEqual(big_decimal(self.pi), BIG_DECIMAL_PI) - - -if __name__ == '__main__': - unittest.main() diff --git a/test/core/test_operators.py b/test/core/test_operators.py index 4bec388..9b5e870 100644 --- a/test/core/test_operators.py +++ b/test/core/test_operators.py @@ -1,10 +1,12 @@ import unittest import random import string -from tuprolog.core import * -from tuprolog.core.operators import * -import jpype.imports -from java.lang import IllegalArgumentException # type: ignore +from tuprolog.core import integer, atom, struct +from tuprolog.core.operators import operator, specifier, operator_set +from tuprolog.core.operators import XF, YF, FX, FY, XFY, YFX, XFX, OperatorSet +from tuprolog.core.operators import EMPTY_OPERATORS, DEFAULT_OPERATORS, STANDARD_OPERATORS +import jpype.imports # noqa: F401 +from java.lang import IllegalArgumentException # type: ignore class AbstractTestOperatorStuff(unittest.TestCase): @@ -139,7 +141,3 @@ def test_constant_operators_set(self): # Assert standard operators are in set of builtin operators for op in STANDARD_OPERATORS: self.assertTrue(op in self.all_builtin_operators) - - -if __name__ == '__main__': - unittest.main() diff --git a/test/core/test_parsing.py b/test/core/test_parsing.py index a5fe001..777ab4d 100644 --- a/test/core/test_parsing.py +++ b/test/core/test_parsing.py @@ -1 +1 @@ -# TODO: write tests \ No newline at end of file +# TODO: write tests diff --git a/test/core/test_scope.py b/test/core/test_scope.py index 93cb24c..c96db19 100644 --- a/test/core/test_scope.py +++ b/test/core/test_scope.py @@ -29,6 +29,3 @@ def test_variables_reuse(self): def test_attributes(self): s = scope() self.assertEqual(s.fail, FAIL) - -if __name__ == '__main__': - unittest.main() diff --git a/test/core/test_substitution.py b/test/core/test_substitution.py index bf027f5..126746f 100644 --- a/test/core/test_substitution.py +++ b/test/core/test_substitution.py @@ -1,9 +1,9 @@ import unittest -from tuprolog.core import substitution, var, struct, atom, scope +from tuprolog.core import substitution, struct, atom, scope class TestSubstitution(unittest.TestCase): - + def test_substitution_creation(self): sub = substitution({}) self.assertEqual(0, len(sub)) diff --git a/test/core/test_terms.py b/test/core/test_terms.py index e9b341e..c8e8b99 100644 --- a/test/core/test_terms.py +++ b/test/core/test_terms.py @@ -1,5 +1,6 @@ import unittest -from tuprolog.core import * +from tuprolog.core import atom, integer, real, var, TRUE, FALSE, FAIL, struct + class TestTermCreation(unittest.TestCase): @@ -36,8 +37,4 @@ def test_struct_creation(self): self.assertEqual(self.struct.getArgAt(1), self.integer) self.assertEqual(self.struct.getArgAt(2), self.real) - self.assertEqual(self.struct, self.struct2) - - -if __name__ == '__main__': - unittest.main() + self.assertEqual(self.struct, self.struct2) diff --git a/test/core/test_try_except.py b/test/core/test_try_except.py index 9e000c8..76b41cb 100644 --- a/test/core/test_try_except.py +++ b/test/core/test_try_except.py @@ -1,6 +1,6 @@ import unittest from tuprolog.core import Substitution, Atom -from tuprolog.core.exception import * +from tuprolog.core.exception import TuPrologException, SubstitutionException, SubstitutionApplicationException class TestExceptions(unittest.TestCase): @@ -10,7 +10,7 @@ def test_TuprologException(self): raise TuPrologException("test") except TuPrologException as e: self.assertEqual("test", e.message) - + def test_SubstitutionException(self): sub = Substitution.empty() try: @@ -28,7 +28,3 @@ def test_SubstitutionApplicationException(self): self.assertEqual("test", e.message) self.assertEqual(sub, e.substitution) self.assertEqual(term, e.term) - - -if __name__ == '__main__': - unittest.main() diff --git a/test/core/test_visitors.py b/test/core/test_visitors.py index 2b32d6f..851585a 100644 --- a/test/core/test_visitors.py +++ b/test/core/test_visitors.py @@ -1,12 +1,6 @@ import unittest from tuprolog.core import Atom, Integer, Var from tuprolog.core import AbstractTermVisitor -import jpype.imports -import kotlin.jvm.functions as _functions # type: ignore - -import unittest -from tuprolog.core import * -from tuprolog.core import AbstractTermVisitor class TestVisitors(unittest.TestCase): @@ -18,7 +12,3 @@ def defaultValue(self, term): visitor = MyVisitor() for term in [Atom.of('a'), Integer.of(1), Var.of("X")]: self.assertEqual(term.accept(visitor), 'a') - - -if __name__ == '__main__': - unittest.main() diff --git a/test/post_install_test.py b/test/post_install_test.py index 2bc013e..8235b27 100644 --- a/test/post_install_test.py +++ b/test/post_install_test.py @@ -1,5 +1,4 @@ -from tuprolog.core import * -from tuprolog.core.parsing import * +from tuprolog.core import TermFormatter, Struct, Integer, Real, Term, Numeric, numeric, var, struct, real from tuprolog.core import AbstractTermVisitor formatter = TermFormatter.prettyExpressions() @@ -41,10 +40,6 @@ def absolute(term: Term): return term -def is_sum(term: Struct): - return term.getArity() == 2 and term.getFunctor() == '+' - - def foldr(accumulator, iterable, default=None): items = list(iterable) if len(items) == 0: diff --git a/test/solve/problog/test_problog_example.py b/test/solve/problog/test_problog_example.py index e288d1f..d312098 100644 --- a/test/solve/problog/test_problog_example.py +++ b/test/solve/problog/test_problog_example.py @@ -5,6 +5,7 @@ from tuprolog.solve.problog import problog_solver from tuprolog.solve.problog.operators import PROBLOG_OPERATORS + class ExemplifyProblog(unittest.TestCase): def setUp(self) -> None: @@ -16,7 +17,7 @@ def setUp(self) -> None: 0.3::edge(3,4). 0.8::edge(4,5). 0.2::edge(5,6). - + path(X,Y) :- edge(X,Y). path(X,Y) :- edge(X,Z),Y \\== Z,path(Z,Y). """ @@ -51,7 +52,3 @@ def test_problog(self): 'yes: path(4, 6) with probability 0.16000000000000003' ] ) - - -if __name__ == '__main__': - unittest.main() diff --git a/test/theory/test_theory.py b/test/theory/test_theory.py index 9961744..2134e7e 100644 --- a/test/theory/test_theory.py +++ b/test/theory/test_theory.py @@ -1,8 +1,8 @@ import unittest from tuprolog.core import clause, var, struct, atom -from tuprolog.jvmutils import Iterable from tuprolog.theory import theory + class TestTheory(unittest.TestCase): def test_empty_theory(self): t = theory() @@ -13,8 +13,13 @@ def test_empty_theory(self): def test_retract(self): A = var('A') a = atom('a') - f = lambda arg: struct('f', arg) - g = lambda arg: struct('g', arg) + + def f(arg): + return struct('f', arg) + + def g(arg): + return struct('g', arg) + t = theory([ c1 := clause(f(A), g(A)), clause(g(a)), @@ -26,8 +31,12 @@ def test_retract(self): def test_unificator(self): A = var('A') a = atom('a') - f = lambda arg: struct('f', arg) - g = lambda arg: struct('g', arg) + + def f(arg): + return struct('f', arg) + + def g(arg): + return struct('g', arg) t = theory([ clause(g(a)), diff --git a/test/unify/test_unify.py b/test/unify/test_unify.py index 3b2faea..414346b 100644 --- a/test/unify/test_unify.py +++ b/test/unify/test_unify.py @@ -3,6 +3,7 @@ from tuprolog.core import scope from tuprolog.unify import DEFAULT_UNIFICATOR + class TestSubstitutionMerge(unittest.TestCase): def test_merge_with(self): s = scope("X", "Y", "Z") diff --git a/tuprolog/__init__.py b/tuprolog/__init__.py index 3dbb3c9..9b9022e 100644 --- a/tuprolog/__init__.py +++ b/tuprolog/__init__.py @@ -14,8 +14,8 @@ install_java_if_missing() jpype.startJVM(classpath=jars) -import jpype.imports -from it.unibo import tuprolog as _tuprolog # type: ignore +import jpype.imports # noqa: F401, E402 +from it.unibo import tuprolog as _tuprolog # type: ignore # noqa: E402 Info = _tuprolog.Info diff --git a/tuprolog/core/_api.py b/tuprolog/core/_api.py index 48b6521..6b16f32 100644 --- a/tuprolog/core/_api.py +++ b/tuprolog/core/_api.py @@ -4,7 +4,9 @@ from tuprolog.pyutils import iterable_or_varargs from tuprolog.jvmutils import jiterable, jmap from tuprolog.math import big_integer, big_decimal, BigInteger, BigDecimal -from ._definitions import Atom, Block, Clause, Cons, Directive, EmptyBlock, EmptyList, Fact, Indicator, Integer, List, Numeric, Real, Rule, Scope, Struct, Substitution, Term, Tuple, Truth, Var +from ._definitions import Atom, Block, Clause, Cons, Directive, EmptyBlock +from ._definitions import EmptyList, Fact, Indicator, Integer, List, Numeric +from ._definitions import Real, Rule, Scope, Struct, Substitution, Term, Tuple, Truth, Var def atom(string: str) -> Atom: diff --git a/tuprolog/core/_definitions.py b/tuprolog/core/_definitions.py index 094dd65..4b589f8 100644 --- a/tuprolog/core/_definitions.py +++ b/tuprolog/core/_definitions.py @@ -1,7 +1,7 @@ from jpype import JImplements, JOverride from tuprolog import logger -import jpype.imports -import it.unibo.tuprolog.core as _core # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.core as _core # type: ignore Applicable = _core.Applicable diff --git a/tuprolog/core/exception.py b/tuprolog/core/exception.py index a17de69..fd4ae2a 100644 --- a/tuprolog/core/exception.py +++ b/tuprolog/core/exception.py @@ -1,6 +1,6 @@ from tuprolog import logger -import jpype.imports -import it.unibo.tuprolog.core.exception as _exceptions # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.core.exception as _exceptions # type: ignore TuPrologException = _exceptions.TuPrologException diff --git a/tuprolog/core/impl.py b/tuprolog/core/impl.py index 1a90964..fb5819b 100644 --- a/tuprolog/core/impl.py +++ b/tuprolog/core/impl.py @@ -1,7 +1,7 @@ from tuprolog import logger from tuprolog.core import TermFormatter -import jpype.imports -import it.unibo.tuprolog.core.impl as _impl # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.core.impl as _impl # type: ignore DefaultTermFormatter = _impl.SimpleTermFormatter diff --git a/tuprolog/core/operators/__init__.py b/tuprolog/core/operators/__init__.py index 1bb2893..9f2c6e8 100644 --- a/tuprolog/core/operators/__init__.py +++ b/tuprolog/core/operators/__init__.py @@ -4,8 +4,8 @@ from tuprolog.pyutils import iterable_or_varargs from tuprolog.core import Atom, Integer, Struct, Term from ._ktadapt import * -import jpype.imports -import it.unibo.tuprolog.core.operators as _operators # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.core.operators as _operators # type: ignore Operator = _operators.Operator diff --git a/tuprolog/core/parsing/__init__.py b/tuprolog/core/parsing/__init__.py index 1f27876..18683f4 100644 --- a/tuprolog/core/parsing/__init__.py +++ b/tuprolog/core/parsing/__init__.py @@ -1,11 +1,11 @@ from typing import Union, Iterable from tuprolog import logger -from tuprolog.jvmutils import InputStream +from tuprolog.jvmioutils import InputStream from tuprolog.core import Term, Struct, Constant, Var, Atom, Numeric, Integer, Real, Clause from tuprolog.core.operators import OperatorSet, DEFAULT_OPERATORS from ._ktadapt import * -import jpype.imports -import it.unibo.tuprolog.core.parsing as _parsing # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.core.parsing as _parsing # type: ignore TermParser = _parsing.TermParser diff --git a/tuprolog/jvmioutils.py b/tuprolog/jvmioutils.py index 35040e5..4fe499b 100644 --- a/tuprolog/jvmioutils.py +++ b/tuprolog/jvmioutils.py @@ -2,9 +2,9 @@ from io import IOBase, SEEK_SET from tuprolog import logger from jpype import JImplementationFor, JOverride -import jpype.imports -import java.io as _jio # type: ignore -import java.nio.file as _jnio_file # type: ignore +import jpype.imports # noqa: F401 +import java.io as _jio # type: ignore +import java.nio.file as _jnio_file # type: ignore InputStream = _jio.InputStream @@ -49,10 +49,10 @@ def isatty(self): def readable(self): return True - def seekable(self): + def seekable(self): return False - def writable(self): + def writable(self): return False def _buffer(self): diff --git a/tuprolog/jvmutils.py b/tuprolog/jvmutils.py index 6b4e594..f97813c 100644 --- a/tuprolog/jvmutils.py +++ b/tuprolog/jvmutils.py @@ -1,14 +1,13 @@ from typing import Iterable as PyIterable, Iterator as PyIterator, Mapping, MutableMapping, Callable, Any from jpype import JImplements, JOverride, JConversion, JImplementationFor, JArray from tuprolog import logger -from .jvmioutils import * -import jpype.imports -from _jpype import _JObject as JObjectClass, _JMethod as JMethodClass # type: ignore -import java.util as _jutils # type: ignore -import java.lang as _jlang # type: ignore -import kotlin as _kotlin # type: ignore -import kotlin.sequences as _ksequences # type: ignore -import it.unibo.tuprolog.utils as _tuprolog_utils # type: ignore +import jpype.imports # noqa: F401 +from _jpype import _JObject as JObjectClass, _JMethod as JMethodClass # type: ignore +import java.util as _jutils # type: ignore +import java.lang as _jlang # type: ignore +import kotlin as _kotlin # type: ignore +import kotlin.sequences as _ksequences # type: ignore +import it.unibo.tuprolog.utils as _tuprolog_utils # type: ignore Arrays = _jutils.Arrays @@ -202,7 +201,10 @@ def __ge__(self, other): def to_snake_case(camel_str: str) -> str: - return "".join("_" + x.lower() if x.isupper() and camel_str[i + 1:i + 2].islower() else x for i, x in enumerate(camel_str)).lstrip("_") + return "".join( + "_" + x.lower() if x.isupper() and camel_str[i + 1:i + 2].islower() else x + for i, x in enumerate(camel_str) + ).lstrip("_") @JImplementationFor("java.lang.Object") @@ -294,4 +296,5 @@ def invoke(self, *args): _kt_function_classes[arity] = _KtFunctionN return _kt_function_classes[arity] + logger.debug("Configure JVM-specific extensions") diff --git a/tuprolog/libs/java.py b/tuprolog/libs/java.py index 3ebd2fc..a5a4ded 100644 --- a/tuprolog/libs/java.py +++ b/tuprolog/libs/java.py @@ -4,19 +4,29 @@ import logging from pathlib import Path + JAVA_HOME = Path(__file__).parent / 'java' + CLASSPATH = Path(__file__).parent + logger = logging.getLogger('tuprolog') + def install_java_if_missing() -> Path: if JAVA_HOME.exists(): return java_version = os.getenv('JAVA_VERSION', '11') destination_folder = str(CLASSPATH) logger.info(f'Downloading Java {java_version} in {destination_folder}') - installation_path = Path(jdk.install(java_version, jre=not java_version.startswith('16'), path=destination_folder)) # Java 16 doesn't have a JRE + installation_path = Path( + jdk.install( + java_version, + jre=not java_version.startswith('16'), # Java 16 doesn't have a JRE + path=destination_folder + ) + ) destination_folder = JAVA_HOME logger.info(f'Installing Java {java_version} in {destination_folder}') shutil.copytree(installation_path, destination_folder, dirs_exist_ok=True) diff --git a/tuprolog/math/_definitions.py b/tuprolog/math/_definitions.py index 27d2899..35d9e63 100644 --- a/tuprolog/math/_definitions.py +++ b/tuprolog/math/_definitions.py @@ -1,6 +1,6 @@ -import jpype.imports -import org.gciatto.kt.math as _ktmath # type: ignore -import java.lang as _java_lang # type: ignore +import jpype.imports # noqa: F401 +import org.gciatto.kt.math as _ktmath # type: ignore +import java.lang as _java_lang # type: ignore BigInteger = _ktmath.BigInteger diff --git a/tuprolog/solve/__init__.py b/tuprolog/solve/__init__.py index 51079b6..44b4e8e 100644 --- a/tuprolog/solve/__init__.py +++ b/tuprolog/solve/__init__.py @@ -5,8 +5,8 @@ from tuprolog.solve.exception import ResolutionException from tuprolog.jvmutils import jlist, jmap, JavaSystem from ._ktadapt import * -import jpype.imports -import it.unibo.tuprolog.solve as _solve # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve as _solve # type: ignore ExecutionContext = _solve.ExecutionContext diff --git a/tuprolog/solve/channel/__init__.py b/tuprolog/solve/channel/__init__.py index a9650a7..56def41 100644 --- a/tuprolog/solve/channel/__init__.py +++ b/tuprolog/solve/channel/__init__.py @@ -2,9 +2,9 @@ from functools import singledispatch from tuprolog import logger from tuprolog.jvmutils import jmap, kfunction -import jpype.imports -import it.unibo.tuprolog.solve.channel as _channel # type: ignore -import kotlin.jvm.functions as _kfunctions # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.channel as _channel # type: ignore +import kotlin.jvm.functions as _kfunctions # type: ignore Channel = _channel.Channel diff --git a/tuprolog/solve/classic/__init__.py b/tuprolog/solve/classic/__init__.py index f2b5fe4..d8206e5 100644 --- a/tuprolog/solve/classic/__init__.py +++ b/tuprolog/solve/classic/__init__.py @@ -33,4 +33,5 @@ def classic_solver( def classic_solver_factory() -> SolverFactory: return _CLASSIC_SOLVER_FACTORY -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.classic.*") \ No newline at end of file + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.classic.*") diff --git a/tuprolog/solve/data/__init__.py b/tuprolog/solve/data/__init__.py index 7d2a30e..60f25fb 100644 --- a/tuprolog/solve/data/__init__.py +++ b/tuprolog/solve/data/__init__.py @@ -2,8 +2,8 @@ from tuprolog import logger from tuprolog.jvmutils import Map, jmap from tuprolog.pyutils import dict_or_keyword_args -import jpype.imports -import it.unibo.tuprolog.solve.data as _data # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.data as _data # type: ignore CustomDataStore = _data.CustomDataStore diff --git a/tuprolog/solve/exception/__init__.py b/tuprolog/solve/exception/__init__.py index c03463a..e049a36 100644 --- a/tuprolog/solve/exception/__init__.py +++ b/tuprolog/solve/exception/__init__.py @@ -1,6 +1,6 @@ from tuprolog import logger -import jpype.imports -import it.unibo.tuprolog.solve.exception as _exceptions # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception as _exceptions # type: ignore HaltException = _exceptions.HaltException diff --git a/tuprolog/solve/exception/error/domain/__init__.py b/tuprolog/solve/exception/error/domain/__init__.py index af2799a..6b95cb8 100644 --- a/tuprolog/solve/exception/error/domain/__init__.py +++ b/tuprolog/solve/exception/error/domain/__init__.py @@ -2,8 +2,8 @@ from tuprolog import logger from tuprolog.core import Term from tuprolog.solve import ExecutionContext, Signature -import jpype.imports -import it.unibo.tuprolog.solve.exception.error as errors # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as errors # type: ignore DomainError = errors.DomainError diff --git a/tuprolog/solve/exception/error/evaluation/__init__.py b/tuprolog/solve/exception/error/evaluation/__init__.py index f27d70c..f2ed1c7 100644 --- a/tuprolog/solve/exception/error/evaluation/__init__.py +++ b/tuprolog/solve/exception/error/evaluation/__init__.py @@ -2,8 +2,8 @@ from tuprolog import logger from tuprolog.core import Term, atom from tuprolog.solve import ExecutionContext -import jpype.imports -import it.unibo.tuprolog.solve.exception.error as errors # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as errors # type: ignore EvaluationError = errors.EvaluationError diff --git a/tuprolog/solve/exception/error/existence/__init__.py b/tuprolog/solve/exception/error/existence/__init__.py index 4a8f8c8..c34a236 100644 --- a/tuprolog/solve/exception/error/existence/__init__.py +++ b/tuprolog/solve/exception/error/existence/__init__.py @@ -2,8 +2,8 @@ from tuprolog import logger from tuprolog.core import Term, Atom from tuprolog.solve import ExecutionContext, Signature -import jpype.imports -import it.unibo.tuprolog.solve.exception.error as errors # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as errors # type: ignore ExistenceError = errors.ExistenceError diff --git a/tuprolog/solve/exception/error/instantiation/__init__.py b/tuprolog/solve/exception/error/instantiation/__init__.py index 01c7f20..7056b92 100644 --- a/tuprolog/solve/exception/error/instantiation/__init__.py +++ b/tuprolog/solve/exception/error/instantiation/__init__.py @@ -1,8 +1,8 @@ from tuprolog import logger from tuprolog.core import Var from tuprolog.solve import ExecutionContext, Signature -import jpype.imports -import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore InstantiationError = _errors.InstantiationError diff --git a/tuprolog/solve/exception/error/message/__init__.py b/tuprolog/solve/exception/error/message/__init__.py index a0b7611..c8549aa 100644 --- a/tuprolog/solve/exception/error/message/__init__.py +++ b/tuprolog/solve/exception/error/message/__init__.py @@ -1,8 +1,8 @@ from tuprolog import logger from tuprolog.core import Term from tuprolog.solve import ExecutionContext -import jpype.imports -import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore MessageError = _errors.MessageError diff --git a/tuprolog/solve/exception/error/permission/__init__.py b/tuprolog/solve/exception/error/permission/__init__.py index 2a195e8..11a9f65 100644 --- a/tuprolog/solve/exception/error/permission/__init__.py +++ b/tuprolog/solve/exception/error/permission/__init__.py @@ -2,8 +2,8 @@ from tuprolog import logger from tuprolog.core import Term from tuprolog.solve import ExecutionContext, Signature -import jpype.imports -import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore PermissionError = _errors.PermissionError diff --git a/tuprolog/solve/exception/error/representation/__init__.py b/tuprolog/solve/exception/error/representation/__init__.py index b85e7ee..609c084 100644 --- a/tuprolog/solve/exception/error/representation/__init__.py +++ b/tuprolog/solve/exception/error/representation/__init__.py @@ -2,8 +2,8 @@ from tuprolog import logger from tuprolog.core import Term from tuprolog.solve import ExecutionContext, Signature -import jpype.imports -import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore RepresentationError = _errors.RepresentationError diff --git a/tuprolog/solve/exception/error/syntax/__init__.py b/tuprolog/solve/exception/error/syntax/__init__.py index 954ca89..35c9450 100644 --- a/tuprolog/solve/exception/error/syntax/__init__.py +++ b/tuprolog/solve/exception/error/syntax/__init__.py @@ -1,7 +1,7 @@ from tuprolog import logger from tuprolog.solve import ExecutionContext -import jpype.imports -import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore SyntaxError = _errors.SyntaxError diff --git a/tuprolog/solve/exception/error/system/__init__.py b/tuprolog/solve/exception/error/system/__init__.py index ff94fb7..13b8a5c 100644 --- a/tuprolog/solve/exception/error/system/__init__.py +++ b/tuprolog/solve/exception/error/system/__init__.py @@ -1,13 +1,13 @@ from tuprolog import logger from tuprolog.solve import ExecutionContext from tuprolog.solve.exception import LogicError -import jpype.imports -import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore - +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore SystemError = _errors.SyntaxError + def syntax_error(context: ExecutionContext, message: str, exception) -> SystemError: if isinstance(exception, LogicError): return SystemError.forUncaughtError(context, message, exception) diff --git a/tuprolog/solve/exception/error/type/__init__.py b/tuprolog/solve/exception/error/type/__init__.py index e5fd510..4cfe91a 100644 --- a/tuprolog/solve/exception/error/type/__init__.py +++ b/tuprolog/solve/exception/error/type/__init__.py @@ -2,56 +2,79 @@ from tuprolog import logger from tuprolog.core import Term from tuprolog.solve import ExecutionContext, Signature -import jpype.imports -import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore TypeError = _errors.TypeError + Type = TypeError.Expected + TYPE_ATOM = Type.ATOM + TYPE_ATOMIC = Type.ATOMIC + TYPE_BOOLEAN = Type.BOOLEAN + TYPE_BYTE = Type.BYTE + TYPE_CALLABLE = Type.CALLABLE + TYPE_CHARACTER = Type.CHARACTER + TYPE_COMPOUND = Type.COMPOUND + TYPE_DEALIASING_EXPRESSION = Type.DEALIASING_EXPRESSION + TYPE_EVALUABLE = Type.EVALUABLE + TYPE_FLOAT = Type.FLOAT + TYPE_INTEGER = Type.INTEGER + TYPE_IN_CHARACTER = Type.IN_CHARACTER + TYPE_LIST = Type.LIST + TYPE_NUMBER = Type.NUMBER + TYPE_OBJECT_REFERENCE = Type.OBJECT_REFERENCE + TYPE_PAIR = Type.PAIR + TYPE_PREDICATE_INDICATOR = Type.PREDICATE_INDICATOR + TYPE_REFERENCE = Type.REFERENCE + TYPE_TYPE_REFERENCE = Type.TYPE_REFERENCE + TYPE_URL = Type.URL + TYPE_VARIABLE = Type.VARIABLE + def type_error_for_flag_values( context: ExecutionContext, procedure: Signature, diff --git a/tuprolog/solve/exception/warning/__init__.py b/tuprolog/solve/exception/warning/__init__.py index 018d292..939fe13 100644 --- a/tuprolog/solve/exception/warning/__init__.py +++ b/tuprolog/solve/exception/warning/__init__.py @@ -1,8 +1,8 @@ from tuprolog import logger from tuprolog.core import Struct from tuprolog.solve import ExecutionContext, ResolutionException, Signature -import jpype.imports -import it.unibo.tuprolog.solve.exception.warning as _warnings # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.warning as _warnings # type: ignore InitializationIssue = _warnings.InitializationIssue diff --git a/tuprolog/solve/flags/__init__.py b/tuprolog/solve/flags/__init__.py index e9bc36e..c1b88a8 100644 --- a/tuprolog/solve/flags/__init__.py +++ b/tuprolog/solve/flags/__init__.py @@ -2,8 +2,8 @@ from tuprolog import logger from tuprolog.core import Term from tuprolog.jvmutils import kpair, jmap, jarray, Pair -import jpype.imports -import it.unibo.tuprolog.solve.flags as _flags # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.flags as _flags # type: ignore DoubleQuotes = _flags.DoubleQuotes diff --git a/tuprolog/solve/function/__init__.py b/tuprolog/solve/function/__init__.py index 9b56db0..c9b5799 100644 --- a/tuprolog/solve/function/__init__.py +++ b/tuprolog/solve/function/__init__.py @@ -3,8 +3,8 @@ from tuprolog.core import Term from tuprolog.solve import ExecutionContext, Signature, current_time_instant, MAX_TIMEOUT from tuprolog.solve.primitive import SolveRequest -import jpype.imports -import it.unibo.tuprolog.solve.function as _function # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.function as _function # type: ignore LogicFunction = _function.LogicFunction diff --git a/tuprolog/solve/library/__init__.py b/tuprolog/solve/library/__init__.py index 89f77ae..1f1c2fd 100644 --- a/tuprolog/solve/library/__init__.py +++ b/tuprolog/solve/library/__init__.py @@ -6,8 +6,8 @@ from tuprolog.solve import Signature from tuprolog.solve.primitive import Primitive from tuprolog.solve.function import LogicFunction -import jpype.imports -import it.unibo.tuprolog.solve.library as _library # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.library as _library # type: ignore Library = _library.Library @@ -54,4 +54,4 @@ def libraries( return reduce(lambda a, b: a.plus(b), all_libraries, Library.of({}, [], operator_set(), {})) -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.library.*") \ No newline at end of file +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.library.*") diff --git a/tuprolog/solve/library/exception/__init__.py b/tuprolog/solve/library/exception/__init__.py index 6ec1e4f..bbbe199 100644 --- a/tuprolog/solve/library/exception/__init__.py +++ b/tuprolog/solve/library/exception/__init__.py @@ -1,6 +1,6 @@ from tuprolog import logger -import jpype.imports -import it.unibo.tuprolog.solve.library.exception as _exception # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.library.exception as _exception # type: ignore AlreadyLoadedLibraryException = _exception.AlreadyLoadedLibraryException diff --git a/tuprolog/solve/plp/__init__.py b/tuprolog/solve/plp/__init__.py index 8f42516..0a23819 100644 --- a/tuprolog/solve/plp/__init__.py +++ b/tuprolog/solve/plp/__init__.py @@ -2,8 +2,8 @@ from tuprolog import logger from tuprolog.utils import Taggable from tuprolog.solve import SolveOptions, solve_options as _solve_options, MAX_TIMEOUT, ALL_SOLUTIONS -import jpype.imports -import it.unibo.tuprolog.solve as _solve # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve as _solve # type: ignore ProbExtensions = _solve.ProbExtensions diff --git a/tuprolog/solve/primitive/__init__.py b/tuprolog/solve/primitive/__init__.py index 0c1c340..b4439a4 100644 --- a/tuprolog/solve/primitive/__init__.py +++ b/tuprolog/solve/primitive/__init__.py @@ -4,8 +4,8 @@ from tuprolog.solve import ExecutionContext, Signature, Solution, current_time_instant, MAX_TIMEOUT from tuprolog.pyutils import iterable_or_varargs from tuprolog.jvmutils import jlist -import jpype.imports -import it.unibo.tuprolog.solve.primitive as _primitive # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.primitive as _primitive # type: ignore Primitive = _primitive.Primitive diff --git a/tuprolog/solve/problog/operators.py b/tuprolog/solve/problog/operators.py index f71633b..34619be 100644 --- a/tuprolog/solve/problog/operators.py +++ b/tuprolog/solve/problog/operators.py @@ -1,6 +1,6 @@ from tuprolog import logger -import jpype.imports -import it.unibo.tuprolog.solve.problog as _problog # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.problog as _problog # type: ignore Operators = _problog.Operators diff --git a/tuprolog/solve/sideffcts/__init__.py b/tuprolog/solve/sideffcts/__init__.py index 1a8c110..74b7304 100644 --- a/tuprolog/solve/sideffcts/__init__.py +++ b/tuprolog/solve/sideffcts/__init__.py @@ -6,8 +6,8 @@ from tuprolog.core.operators import Operator, OperatorSet from tuprolog.solve.library import Library, libraries as new_libraries from tuprolog.solve.channel import InputChannel, OutputChannel -import jpype.imports -from it.unibo.tuprolog.solve.sideffects import SideEffect # type: ignore +import jpype.imports # noqa: F401 +from it.unibo.tuprolog.solve.sideffects import SideEffect # type: ignore def _forward_iterable_or_varargs(callable, args, *callable_args): diff --git a/tuprolog/solve/stdlib/__init__.py b/tuprolog/solve/stdlib/__init__.py index e583d78..0bfdef5 100644 --- a/tuprolog/solve/stdlib/__init__.py +++ b/tuprolog/solve/stdlib/__init__.py @@ -1,6 +1,6 @@ from tuprolog import logger -import jpype.imports -import it.unibo.tuprolog.solve.stdlib as _stdlib # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.stdlib as _stdlib # type: ignore CommonBuiltins = _stdlib.CommonBuiltins diff --git a/tuprolog/solve/stdlib/function/__init__.py b/tuprolog/solve/stdlib/function/__init__.py index 7211f49..1f25ce7 100644 --- a/tuprolog/solve/stdlib/function/__init__.py +++ b/tuprolog/solve/stdlib/function/__init__.py @@ -1,6 +1,6 @@ from tuprolog import logger -import jpype.imports -import it.unibo.tuprolog.solve.stdlib.function as _function # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.stdlib.function as _function # type: ignore AbsoluteValue = _function.AbsoluteValue.INSTANCE diff --git a/tuprolog/solve/stdlib/primitive/__init__.py b/tuprolog/solve/stdlib/primitive/__init__.py index 5c4bf01..45d84cd 100644 --- a/tuprolog/solve/stdlib/primitive/__init__.py +++ b/tuprolog/solve/stdlib/primitive/__init__.py @@ -1,6 +1,6 @@ from tuprolog import logger -import jpype.imports -import it.unibo.tuprolog.solve.stdlib.primitive as _primitive # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.stdlib.primitive as _primitive # type: ignore Abolish = _primitive.Abolish.INSTANCE diff --git a/tuprolog/solve/stdlib/rule/__init__.py b/tuprolog/solve/stdlib/rule/__init__.py index 433d8ea..a3d9250 100644 --- a/tuprolog/solve/stdlib/rule/__init__.py +++ b/tuprolog/solve/stdlib/rule/__init__.py @@ -1,7 +1,7 @@ from tuprolog import logger from tuprolog.solve import signature -import jpype.imports -import it.unibo.tuprolog.solve.stdlib.rule as _rule # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.stdlib.rule as _rule # type: ignore KtAppend = _rule.Append diff --git a/tuprolog/theory/_api.py b/tuprolog/theory/_api.py index f79896e..f75c61f 100644 --- a/tuprolog/theory/_api.py +++ b/tuprolog/theory/_api.py @@ -3,7 +3,7 @@ from tuprolog.unify import Unificator from tuprolog.jvmutils import jiterable from tuprolog.pyutils import iterable_or_varargs -from ._definitions import * +from ._definitions import Theory, MutableTheory def theory(*clauses: Union[Clause, Iterable[Clause]]) -> Theory: diff --git a/tuprolog/theory/_definitions.py b/tuprolog/theory/_definitions.py index cffc997..398d7fc 100644 --- a/tuprolog/theory/_definitions.py +++ b/tuprolog/theory/_definitions.py @@ -1,6 +1,6 @@ from tuprolog import logger -import jpype.imports -import it.unibo.tuprolog.theory as _theory # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.theory as _theory # type: ignore Theory = _theory.Theory diff --git a/tuprolog/theory/parsing/__init__.py b/tuprolog/theory/parsing/__init__.py index 90117d0..e9e227d 100644 --- a/tuprolog/theory/parsing/__init__.py +++ b/tuprolog/theory/parsing/__init__.py @@ -3,11 +3,11 @@ from tuprolog.core import Clause from tuprolog.core.parsing import _factory from tuprolog.theory import Theory -from tuprolog.jvmutils import InputStream +from tuprolog.jvmioutils import InputStream from tuprolog.core.operators import OperatorSet from ._ktadapt import * -import jpype.imports -import it.unibo.tuprolog.theory.parsing as _parsing # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.theory.parsing as _parsing # type: ignore ClausesParser = _parsing.ClausesParser diff --git a/tuprolog/theory/parsing/_ktadapt.py b/tuprolog/theory/parsing/_ktadapt.py index 9567304..bd0bffb 100644 --- a/tuprolog/theory/parsing/_ktadapt.py +++ b/tuprolog/theory/parsing/_ktadapt.py @@ -28,7 +28,6 @@ def parse_clauses(self, input, operators): return list(self.parse_clauses_lazily(input, operators)) - @JImplementationFor("it.unibo.tuprolog.theory.parsing.ClausesReader") class _KtClausesReader: def __jclass_init__(cls): diff --git a/tuprolog/unify/_api.py b/tuprolog/unify/_api.py index 344422c..6492dc9 100644 --- a/tuprolog/unify/_api.py +++ b/tuprolog/unify/_api.py @@ -1,5 +1,5 @@ from tuprolog.core import Term, Substitution -from ._definitions import * +from ._definitions import Unificator, DEFAULT_UNIFICATOR def strict_unificator(context: Substitution = None) -> Unificator: diff --git a/tuprolog/unify/_definitions.py b/tuprolog/unify/_definitions.py index 4fbbb0b..c14b073 100644 --- a/tuprolog/unify/_definitions.py +++ b/tuprolog/unify/_definitions.py @@ -1,6 +1,6 @@ from tuprolog import logger -import jpype.imports -import it.unibo.tuprolog.unify as _unify # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.unify as _unify # type: ignore Unificator = _unify.Unificator diff --git a/tuprolog/unify/exception.py b/tuprolog/unify/exception.py index 4366f1e..afb2463 100644 --- a/tuprolog/unify/exception.py +++ b/tuprolog/unify/exception.py @@ -1,6 +1,6 @@ from tuprolog import logger -import jpype.imports -import it.unibo.tuprolog.unify.exception as _exceptions # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.unify.exception as _exceptions # type: ignore NoUnifyException = _exceptions.NoUnifyException diff --git a/tuprolog/utils/_definitions.py b/tuprolog/utils/_definitions.py index 2085d89..c269d84 100644 --- a/tuprolog/utils/_definitions.py +++ b/tuprolog/utils/_definitions.py @@ -1,6 +1,6 @@ from tuprolog import logger -import jpype.imports -import it.unibo.tuprolog.utils as _utils # type: ignore +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.utils as _utils # type: ignore Castable = _utils.Castable From cdf863561a4303703188f5228dc913278561c84e Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 12 Oct 2023 01:18:21 +0200 Subject: [PATCH 130/154] Update solve file organization --- tuprolog/jvmutils.py | 2 +- tuprolog/solve/__init__.py | 114 +-------------- tuprolog/solve/{_ktadapt.py => _adapters.py} | 0 tuprolog/solve/_api.py | 79 ++++++++++ tuprolog/solve/_definitions.py | 48 ++++++ tuprolog/solve/channel/__init__.py | 99 +------------ tuprolog/solve/channel/_api.py | 77 ++++++++++ tuprolog/solve/channel/_definitions.py | 28 ++++ tuprolog/solve/classic/__init__.py | 37 ----- tuprolog/solve/data/__init__.py | 34 +---- tuprolog/solve/data/_api.py | 16 ++ tuprolog/solve/data/_definitions.py | 19 +++ tuprolog/solve/exception/__init__.py | 17 +-- tuprolog/solve/exception/_definitions.py | 21 +++ .../solve/exception/error/domain/__init__.py | 137 +----------------- tuprolog/solve/exception/error/domain/_api.py | 48 ++++++ .../exception/error/domain/_definitions.py | 129 +++++++++++++++++ .../exception/error/evaluation/__init__.py | 40 +---- .../solve/exception/error/evaluation/_api.py | 19 +++ .../error/evaluation/_definitions.py | 27 ++++ .../exception/error/existence/__init__.py | 75 +--------- .../solve/exception/error/existence/_api.py | 48 ++++++ .../exception/error/existence/_definitions.py | 36 +++++ .../exception/error/instantiation/__init__.py | 30 +--- .../exception/error/instantiation/_api.py | 20 +++ .../error/instantiation/_definitions.py | 9 ++ .../solve/exception/error/message/__init__.py | 17 +-- .../solve/exception/error/message/_api.py | 7 + .../exception/error/message/_definitions.py | 9 ++ .../exception/error/permission/__init__.py | 82 +---------- .../solve/exception/error/permission/_api.py | 28 ++++ .../error/permission/_definitions.py | 75 ++++++++++ .../error/representation/__init__.py | 47 +----- .../exception/error/representation/_api.py | 20 +++ .../error/representation/_definitions.py | 36 +++++ .../solve/exception/error/syntax/__init__.py | 44 +----- tuprolog/solve/exception/error/syntax/_api.py | 34 +++++ .../exception/error/syntax/_definitions.py | 9 ++ .../solve/exception/error/system/__init__.py | 19 +-- tuprolog/solve/exception/error/system/_api.py | 9 ++ .../exception/error/system/_definitions.py | 9 ++ .../solve/exception/error/type/__init__.py | 134 +---------------- tuprolog/solve/exception/error/type/_api.py | 58 ++++++++ .../exception/error/type/_definitions.py | 75 ++++++++++ tuprolog/solve/exception/warning/__init__.py | 30 +--- tuprolog/solve/exception/warning/_api.py | 19 +++ .../solve/exception/warning/_definitions.py | 12 ++ tuprolog/solve/flags/__init__.py | 76 +--------- tuprolog/solve/flags/_api.py | 42 ++++++ tuprolog/solve/flags/_definitions.py | 52 +++++++ tuprolog/solve/function/__init__.py | 60 +------- tuprolog/solve/function/_api.py | 35 +++++ tuprolog/solve/function/_definitions.py | 29 ++++ 53 files changed, 1217 insertions(+), 1059 deletions(-) rename tuprolog/solve/{_ktadapt.py => _adapters.py} (100%) create mode 100644 tuprolog/solve/_api.py create mode 100644 tuprolog/solve/_definitions.py create mode 100644 tuprolog/solve/channel/_api.py create mode 100644 tuprolog/solve/channel/_definitions.py delete mode 100644 tuprolog/solve/classic/__init__.py create mode 100644 tuprolog/solve/data/_api.py create mode 100644 tuprolog/solve/data/_definitions.py create mode 100644 tuprolog/solve/exception/_definitions.py create mode 100644 tuprolog/solve/exception/error/domain/_api.py create mode 100644 tuprolog/solve/exception/error/domain/_definitions.py create mode 100644 tuprolog/solve/exception/error/evaluation/_api.py create mode 100644 tuprolog/solve/exception/error/evaluation/_definitions.py create mode 100644 tuprolog/solve/exception/error/existence/_api.py create mode 100644 tuprolog/solve/exception/error/existence/_definitions.py create mode 100644 tuprolog/solve/exception/error/instantiation/_api.py create mode 100644 tuprolog/solve/exception/error/instantiation/_definitions.py create mode 100644 tuprolog/solve/exception/error/message/_api.py create mode 100644 tuprolog/solve/exception/error/message/_definitions.py create mode 100644 tuprolog/solve/exception/error/permission/_api.py create mode 100644 tuprolog/solve/exception/error/permission/_definitions.py create mode 100644 tuprolog/solve/exception/error/representation/_api.py create mode 100644 tuprolog/solve/exception/error/representation/_definitions.py create mode 100644 tuprolog/solve/exception/error/syntax/_api.py create mode 100644 tuprolog/solve/exception/error/syntax/_definitions.py create mode 100644 tuprolog/solve/exception/error/system/_api.py create mode 100644 tuprolog/solve/exception/error/system/_definitions.py create mode 100644 tuprolog/solve/exception/error/type/_api.py create mode 100644 tuprolog/solve/exception/error/type/_definitions.py create mode 100644 tuprolog/solve/exception/warning/_api.py create mode 100644 tuprolog/solve/exception/warning/_definitions.py create mode 100644 tuprolog/solve/flags/_api.py create mode 100644 tuprolog/solve/flags/_definitions.py create mode 100644 tuprolog/solve/function/_api.py create mode 100644 tuprolog/solve/function/_definitions.py diff --git a/tuprolog/jvmutils.py b/tuprolog/jvmutils.py index f97813c..85f86f0 100644 --- a/tuprolog/jvmutils.py +++ b/tuprolog/jvmutils.py @@ -144,7 +144,7 @@ def jiterator(iterator: PyIterator) -> Iterator: def jmap(dictionary: Mapping) -> Map: assert isinstance(dictionary, Mapping) - return Map@dictionary + return Map @ dictionary def _java_obj_repr(java_object: Object) -> str: diff --git a/tuprolog/solve/__init__.py b/tuprolog/solve/__init__.py index 44b4e8e..ddab90b 100644 --- a/tuprolog/solve/__init__.py +++ b/tuprolog/solve/__init__.py @@ -1,111 +1,3 @@ -from typing import Iterable, Mapping, Any -from functools import singledispatch -from tuprolog import logger -from tuprolog.core import Indicator, Struct, Term, Substitution, EMPTY_UNIFIER, TermFormatter -from tuprolog.solve.exception import ResolutionException -from tuprolog.jvmutils import jlist, jmap, JavaSystem -from ._ktadapt import * -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve as _solve # type: ignore - - -ExecutionContext = _solve.ExecutionContext - -ExecutionContextAware = _solve.ExecutionContextAware - -MutableSolver = _solve.MutableSolver - -Signature = _solve.Signature - -Solution = _solve.Solution - -SolutionFormatter = _solve.SolutionFormatter - -SolveOptions = _solve.SolveOptions - -Solver = _solve.Solver - -SolverFactory = _solve.SolverFactory - -Time = _solve.Time - - -@singledispatch -def signature(name: str, arity: int, vararg: bool = False) -> Signature: - return Signature(name, arity, vararg) - - -@signature.register -def _signature_from_indicator(indicator: Indicator) -> Signature: - return Signature.fromIndicator(indicator) - - -@signature.register -def _signature_from_term(term: Term) -> Signature: - return Signature.fromSignatureTerm(term) - - -@singledispatch -def yes_solution( - signature: Signature, - arguments: Iterable[Term], - substitution: Substitution.Unifier = EMPTY_UNIFIER -) -> Solution.Yes: - return Solution.yes(signature, jlist(arguments), substitution) - - -@yes_solution.register -def _yes_solution_from_query(query: Struct, substitution: Substitution.Unifier = EMPTY_UNIFIER) -> Solution.Yes: - return Solution.yes(query, substitution) - - -@singledispatch -def no_solution(signature: Signature, arguments: Iterable[Term]) -> Solution.No: - return Solution.no(signature, jlist(arguments)) - - -@no_solution.register -def _no_solution_from_query(query: Struct) -> Solution.No: - return Solution.no(query) - - -@singledispatch -def halt_solution(signature: Signature, arguments: Iterable[Term], exception: ResolutionException) -> Solution.Halt: - return Solution.halt(signature, jlist(arguments), exception) - - -@halt_solution.register -def _halt_solution_from_query(query: Struct, exception: ResolutionException) -> Solution.No: - return Solution.halt(query, exception) - - -def current_time_instant() -> int: - return JavaSystem.currentTimeMillis() - - -def solution_formatter(term_formatter: TermFormatter = TermFormatter.prettyExpressions()) -> SolutionFormatter: - return SolutionFormatter.of(term_formatter) - - -MAX_TIMEOUT: int = SolveOptions.MAX_TIMEOUT - -ALL_SOLUTIONS: int = SolveOptions.ALL_SOLUTIONS - - -def solve_options( - lazy: bool = True, - timeout: int = MAX_TIMEOUT, - limit: int = ALL_SOLUTIONS, - custom: Mapping[str, Any] = dict(), - **kwargs: Any -) -> SolveOptions: - opts = dict(kwargs) - for key in custom: - opts[key] = custom[key] - temp = SolveOptions.of(lazy, timeout, limit) - if len(opts) > 0: - return temp.setOptions(jmap(opts)) - return temp - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.*") +import tuprolog.theory._adapters as _ +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/_ktadapt.py b/tuprolog/solve/_adapters.py similarity index 100% rename from tuprolog/solve/_ktadapt.py rename to tuprolog/solve/_adapters.py diff --git a/tuprolog/solve/_api.py b/tuprolog/solve/_api.py new file mode 100644 index 0000000..46fa75c --- /dev/null +++ b/tuprolog/solve/_api.py @@ -0,0 +1,79 @@ +from typing import Iterable, Mapping, Any +from functools import singledispatch +from tuprolog.jvmutils import jlist, jmap, JavaSystem +from tuprolog.core import Indicator, Struct, Term, Substitution, EMPTY_UNIFIER, TermFormatter +from .exception import ResolutionException +from ._definitions import Signature, Solution, SolveOptions, SolutionFormatter, MAX_TIMEOUT, ALL_SOLUTIONS + + +@singledispatch +def signature(name: str, arity: int, vararg: bool = False) -> Signature: + return Signature(name, arity, vararg) + + +@signature.register +def _signature_from_indicator(indicator: Indicator) -> Signature: + return Signature.fromIndicator(indicator) + + +@signature.register +def _signature_from_term(term: Term) -> Signature: + return Signature.fromSignatureTerm(term) + + +@singledispatch +def yes_solution( + signature: Signature, + arguments: Iterable[Term], + substitution: Substitution.Unifier = EMPTY_UNIFIER +) -> Solution.Yes: + return Solution.yes(signature, jlist(arguments), substitution) + + +@yes_solution.register +def _yes_solution_from_query(query: Struct, substitution: Substitution.Unifier = EMPTY_UNIFIER) -> Solution.Yes: + return Solution.yes(query, substitution) + + +@singledispatch +def no_solution(signature: Signature, arguments: Iterable[Term]) -> Solution.No: + return Solution.no(signature, jlist(arguments)) + + +@no_solution.register +def _no_solution_from_query(query: Struct) -> Solution.No: + return Solution.no(query) + + +@singledispatch +def halt_solution(signature: Signature, arguments: Iterable[Term], exception: ResolutionException) -> Solution.Halt: + return Solution.halt(signature, jlist(arguments), exception) + + +@halt_solution.register +def _halt_solution_from_query(query: Struct, exception: ResolutionException) -> Solution.No: + return Solution.halt(query, exception) + + +def current_time_instant() -> int: + return JavaSystem.currentTimeMillis() + + +def solution_formatter(term_formatter: TermFormatter = TermFormatter.prettyExpressions()) -> SolutionFormatter: + return SolutionFormatter.of(term_formatter) + + +def solve_options( + lazy: bool = True, + timeout: int = MAX_TIMEOUT, + limit: int = ALL_SOLUTIONS, + custom: Mapping[str, Any] = dict(), + **kwargs: Any +) -> SolveOptions: + opts = dict(kwargs) + for key in custom: + opts[key] = custom[key] + temp = SolveOptions.of(lazy, timeout, limit) + if len(opts) > 0: + return temp.setOptions(jmap(opts)) + return temp diff --git a/tuprolog/solve/_definitions.py b/tuprolog/solve/_definitions.py new file mode 100644 index 0000000..ecff6f3 --- /dev/null +++ b/tuprolog/solve/_definitions.py @@ -0,0 +1,48 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve as _solve # type: ignore + + +Durable = _solve.Durable + + +ExecutionContext = _solve.ExecutionContext + + +ExecutionContextAware = _solve.ExecutionContextAware + + +MutableSolver = _solve.MutableSolver + + +Signature = _solve.Signature + + +Solution = _solve.Solution + + +SolutionFormatter = _solve.SolutionFormatter + + +SolveOptions = _solve.SolveOptions + + +Solver = _solve.Solver + + +SolverBuilder = _solve.SolverBuilder + + +SolverFactory = _solve.SolverFactory + + +Time = _solve.Time + + +MAX_TIMEOUT: int = SolveOptions.MAX_TIMEOUT + + +ALL_SOLUTIONS: int = SolveOptions.ALL_SOLUTIONS + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.*") diff --git a/tuprolog/solve/channel/__init__.py b/tuprolog/solve/channel/__init__.py index 56def41..3272497 100644 --- a/tuprolog/solve/channel/__init__.py +++ b/tuprolog/solve/channel/__init__.py @@ -1,97 +1,2 @@ -from typing import Callable, Mapping -from functools import singledispatch -from tuprolog import logger -from tuprolog.jvmutils import jmap, kfunction -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.channel as _channel # type: ignore -import kotlin.jvm.functions as _kfunctions # type: ignore - -Channel = _channel.Channel - -ChannelStore = _channel.ChannelStore - -InputChannel = _channel.InputChannel - -InputStore = _channel.InputStore - -OutputChannel = _channel.OutputChannel - -OutputStore = _channel.OutputStore - -Listener = _kfunctions.Function1 - - -def std_in() -> InputChannel: - return InputChannel.stdIn() - - -@singledispatch -def input_channel(generator: Callable, availability_checker: Callable = None) -> InputChannel: - if availability_checker is None: - return InputChannel.of(kfunction(0)(generator)) - else: - return InputChannel.of(kfunction(0)(generator), kfunction(0)(availability_checker)) - - -@input_channel.register -def input_channel_from_string(string: str) -> InputChannel: - return InputChannel.of(string) - - -def input_store(stdin: InputChannel = None, channels: Mapping[str, InputChannel] = None) -> InputStore: - if stdin is None and channels is None: - return InputStore.fromStandard() - elif channels is None: - return InputStore.fromStandard(stdin) - else: - cs = {InputStore.STDIN: stdin or std_in()} - for k, v in channels: - cs[k] = v - return InputStore.of(jmap(cs)) - - -def std_out() -> OutputChannel: - return OutputChannel.stdOut() - - -def std_err() -> OutputChannel: - return OutputChannel.stdErr() - - -def warn() -> OutputChannel: - return OutputChannel.warn() - - -def output_channel(consumer: Callable) -> OutputChannel: - return OutputChannel.of(kfunction(1)(consumer)) - - -def output_store( - stdout: OutputChannel = None, - stderr: OutputChannel = None, - warnings: OutputChannel = None, - channels: Mapping[str, OutputChannel] = None -) -> OutputStore: - if all((channel is None for channel in (stdout, stderr, warnings))): - return OutputStore.fromStandard() - elif channels is None: - return OutputStore.fromStandard( - stdout or std_out(), - stderr or std_err(), - warnings or warn() - ) - else: - cs = { - OutputStore.STDOUT: stdout or std_out(), - OutputStore.STDERR: stderr or std_err() - } - for k, v in channels: - cs[k] = v - return OutputStore.of(jmap(cs), warnings or warn()) - - -def listener(consumer: Callable) -> Listener: - return kfunction(1)(consumer) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.channel.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/channel/_api.py b/tuprolog/solve/channel/_api.py new file mode 100644 index 0000000..6a85ce2 --- /dev/null +++ b/tuprolog/solve/channel/_api.py @@ -0,0 +1,77 @@ +from typing import Callable, Mapping +from functools import singledispatch +from tuprolog.jvmutils import jmap, kfunction +from ._definitions import InputChannel, InputStore, OutputChannel, OutputStore, Listener + + +def std_in() -> InputChannel: + return InputChannel.stdIn() + + +@singledispatch +def input_channel(generator: Callable, availability_checker: Callable = None) -> InputChannel: + if availability_checker is None: + return InputChannel.of(kfunction(0)(generator)) + else: + return InputChannel.of(kfunction(0)(generator), kfunction(0)(availability_checker)) + + +@input_channel.register +def input_channel_from_string(string: str) -> InputChannel: + return InputChannel.of(string) + + +def input_store(stdin: InputChannel = None, channels: Mapping[str, InputChannel] = None) -> InputStore: + if stdin is None and channels is None: + return InputStore.fromStandard() + elif channels is None: + return InputStore.fromStandard(stdin) + else: + cs = {InputStore.STDIN: stdin or std_in()} + for k, v in channels: + cs[k] = v + return InputStore.of(jmap(cs)) + + +def std_out() -> OutputChannel: + return OutputChannel.stdOut() + + +def std_err() -> OutputChannel: + return OutputChannel.stdErr() + + +def warn() -> OutputChannel: + return OutputChannel.warn() + + +def output_channel(consumer: Callable) -> OutputChannel: + return OutputChannel.of(kfunction(1)(consumer)) + + +def output_store( + stdout: OutputChannel = None, + stderr: OutputChannel = None, + warnings: OutputChannel = None, + channels: Mapping[str, OutputChannel] = None +) -> OutputStore: + if all((channel is None for channel in (stdout, stderr, warnings))): + return OutputStore.fromStandard() + elif channels is None: + return OutputStore.fromStandard( + stdout or std_out(), + stderr or std_err(), + warnings or warn() + ) + else: + cs = { + OutputStore.STDOUT: stdout or std_out(), + OutputStore.STDERR: stderr or std_err() + } + for k, v in channels: + cs[k] = v + return OutputStore.of(jmap(cs), warnings or warn()) + + +def listener(consumer: Callable) -> Listener: + return kfunction(1)(consumer) diff --git a/tuprolog/solve/channel/_definitions.py b/tuprolog/solve/channel/_definitions.py new file mode 100644 index 0000000..d260b51 --- /dev/null +++ b/tuprolog/solve/channel/_definitions.py @@ -0,0 +1,28 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.channel as _channel # type: ignore +import kotlin.jvm.functions as _kfunctions # type: ignore + + +Channel = _channel.Channel + + +ChannelStore = _channel.ChannelStore + + +InputChannel = _channel.InputChannel + + +InputStore = _channel.InputStore + + +OutputChannel = _channel.OutputChannel + + +OutputStore = _channel.OutputStore + + +Listener = _kfunctions.Function1 + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.channel.*") diff --git a/tuprolog/solve/classic/__init__.py b/tuprolog/solve/classic/__init__.py deleted file mode 100644 index d8206e5..0000000 --- a/tuprolog/solve/classic/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -from tuprolog import logger -from tuprolog.solve.flags import DEFAULT_FLAG_STORE, FlagStore -from tuprolog.solve.library import libraries, Library -from tuprolog.solve.channel import InputChannel, OutputChannel, std_out, std_in, std_err, warn -from tuprolog.theory import theory, mutable_theory, Theory -from tuprolog.solve import Solver, SolverFactory - - -_CLASSIC_SOLVER_FACTORY = Solver.prolog() - - -def classic_solver( - libraries: Library = libraries(), - flags: FlagStore = DEFAULT_FLAG_STORE, - static_kb: Theory = theory(), - dynamic_kb: Theory = mutable_theory(), - std_in: InputChannel = std_in(), - std_out: OutputChannel = std_out(), - std_err: OutputChannel = std_err(), - warning: OutputChannel = warn(), - mutable: bool = True -) -> Solver: - if mutable: - return _CLASSIC_SOLVER_FACTORY.mutableSolverWithDefaultBuiltins( - libraries, flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning - ) - else: - return _CLASSIC_SOLVER_FACTORY.solverWithDefaultBuiltins( - libraries, flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning - ) - - -def classic_solver_factory() -> SolverFactory: - return _CLASSIC_SOLVER_FACTORY - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.classic.*") diff --git a/tuprolog/solve/data/__init__.py b/tuprolog/solve/data/__init__.py index 60f25fb..3272497 100644 --- a/tuprolog/solve/data/__init__.py +++ b/tuprolog/solve/data/__init__.py @@ -1,32 +1,2 @@ -from typing import Mapping, Any -from tuprolog import logger -from tuprolog.jvmutils import Map, jmap -from tuprolog.pyutils import dict_or_keyword_args -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.data as _data # type: ignore - - -CustomDataStore = _data.CustomDataStore - -CustomData = Map - - -def custom_data(data: Mapping[str, Any] = {}, **kwargs) -> CustomData: - return dict_or_keyword_args(data, kwargs, lambda ds: jmap(ds)) - - -EMPTY_DATA: CustomData = custom_data() - - -def custom_data_store( - persistent: CustomData = EMPTY_DATA, - durable: CustomData = EMPTY_DATA, - ephemeral: CustomData = EMPTY_DATA -) -> CustomDataStore: - return CustomDataStore.empty().copy(persistent, durable, ephemeral) - - -EMPTY_DATA_STORE: CustomDataStore = CustomDataStore.empty() - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.data.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/data/_api.py b/tuprolog/solve/data/_api.py new file mode 100644 index 0000000..dd1fc17 --- /dev/null +++ b/tuprolog/solve/data/_api.py @@ -0,0 +1,16 @@ +from typing import Mapping, Any +from tuprolog.pyutils import dict_or_keyword_args +from tuprolog.jvmutils import jmap +from ._definitions import CustomData, CustomDataStore, EMPTY_DATA + + +def custom_data(data: Mapping[str, Any] = {}, **kwargs) -> CustomData: + return dict_or_keyword_args(data, kwargs, lambda ds: jmap(ds)) + + +def custom_data_store( + persistent: CustomData = EMPTY_DATA, + durable: CustomData = EMPTY_DATA, + ephemeral: CustomData = EMPTY_DATA +) -> CustomDataStore: + return CustomDataStore.empty().copy(persistent, durable, ephemeral) diff --git a/tuprolog/solve/data/_definitions.py b/tuprolog/solve/data/_definitions.py new file mode 100644 index 0000000..49894c1 --- /dev/null +++ b/tuprolog/solve/data/_definitions.py @@ -0,0 +1,19 @@ +from tuprolog import logger +from tuprolog.jvmutils import Map +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.data as _data # type: ignore + + +CustomDataStore = _data.CustomDataStore + + +CustomData = Map + + +EMPTY_DATA: CustomData = Map @ {} + + +EMPTY_DATA_STORE: CustomDataStore = CustomDataStore.empty() + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.data.*") diff --git a/tuprolog/solve/exception/__init__.py b/tuprolog/solve/exception/__init__.py index e049a36..47c7575 100644 --- a/tuprolog/solve/exception/__init__.py +++ b/tuprolog/solve/exception/__init__.py @@ -1,16 +1 @@ -from tuprolog import logger -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.exception as _exceptions # type: ignore - -HaltException = _exceptions.HaltException - -LogicError = _exceptions.LogicError - -ResolutionException = _exceptions.ResolutionException - -TimeOutException = _exceptions.TimeOutException - -Warning = _exceptions.Warning - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.*") +from ._definitions import * diff --git a/tuprolog/solve/exception/_definitions.py b/tuprolog/solve/exception/_definitions.py new file mode 100644 index 0000000..995b9c7 --- /dev/null +++ b/tuprolog/solve/exception/_definitions.py @@ -0,0 +1,21 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception as _exceptions # type: ignore + + +HaltException = _exceptions.HaltException + + +LogicError = _exceptions.LogicError + + +ResolutionException = _exceptions.ResolutionException + + +TimeOutException = _exceptions.TimeOutException + + +Warning = _exceptions.Warning + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.*") diff --git a/tuprolog/solve/exception/error/domain/__init__.py b/tuprolog/solve/exception/error/domain/__init__.py index 6b95cb8..3272497 100644 --- a/tuprolog/solve/exception/error/domain/__init__.py +++ b/tuprolog/solve/exception/error/domain/__init__.py @@ -1,135 +1,2 @@ -from typing import Iterable, Union -from tuprolog import logger -from tuprolog.core import Term -from tuprolog.solve import ExecutionContext, Signature -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.exception.error as errors # type: ignore - -DomainError = errors.DomainError - -Domain = DomainError.Expected - -DOMAIN_wATOM_PROPERTY = Domain.ATOM_PROPERTY - -DOMAIN_BUFFERING_MODE = Domain.BUFFERING_MODE - -DOMAIN_CHARACTER_CODE_LIST = Domain.CHARACTER_CODE_LIST - -DOMAIN_CLOSE_OPTION = Domain.CLOSE_OPTION - -DOMAIN_DATE_TIME = Domain.DATE_TIME - -DOMAIN_EOF_ACTION = Domain.EOF_ACTION - -DOMAIN_FLAG_VALUE = Domain.FLAG_VALUE - -DOMAIN_FORMAT_CONTROL_SEQUENCE = Domain.FORMAT_CONTROL_SEQUENCE - -DOMAIN_IO_MODE = Domain.IO_MODE - -DOMAIN_WELL_FORMED_LIST = Domain.WELL_FORMED_LIST - -DOMAIN_NON_EMPTY_LIST = Domain.NON_EMPTY_LIST - -DOMAIN_NOT_LESS_THAN_ZERO = Domain.NOT_LESS_THAN_ZERO - -DOMAIN_OPERATOR_PRIORITY = Domain.OPERATOR_PRIORITY - -DOMAIN_OPERATOR_SPECIFIER = Domain.OPERATOR_SPECIFIER - -DOMAIN_ORDER = Domain.ORDER - -DOMAIN_OS_FILE_PERMISSION = Domain.OS_FILE_PERMISSION - -DOMAIN_OS_FILE_PROPERTY = Domain.OS_FILE_PROPERTY - -DOMAIN_OS_PATH = Domain.OS_PATH - -DOMAIN_PREDICATE_PROPERTY = Domain.PREDICATE_PROPERTY - -DOMAIN_FLAG = Domain.FLAG - -DOMAIN_READ_OPTION = Domain.READ_OPTION - -DOMAIN_SELECTABLE_ITEM = Domain.SELECTABLE_ITEM - -DOMAIN_SOCKET_ADDRESS = Domain.SOCKET_ADDRESS - -DOMAIN_SOCKET_DOMAIN = Domain.SOCKET_DOMAIN - -DOMAIN_SOURCE_SINK = Domain.SOURCE_SINK - -DOMAIN_STREAM = Domain.STREAM - -DOMAIN_STREAM_OPTION = Domain.STREAM_OPTION - -DOMAIN_STREAM_OR_ALIAS = Domain.STREAM_OR_ALIAS - -DOMAIN_STREAM_POSITION = Domain.STREAM_POSITION - -DOMAIN_STREAM_PROPERTY = Domain.STREAM_PROPERTY - -DOMAIN_STREAM_SEEK_METHOD = Domain.STREAM_SEEK_METHOD - -DOMAIN_STREAM_TYPE = Domain.STREAM_TYPE - -DOMAIN_TERM_STREAM_OR_ALIAS = Domain.TERM_STREAM_OR_ALIAS - -DOMAIN_VAR_BINDING_OPTION = Domain.VAR_BINDING_OPTION - -DOMAIN_WRITE_OPTION = Domain.WRITE_OPTION - -DOMAIN_CLAUSE = Domain.CLAUSE - -DOMAIN_RULE = Domain.RULE - -DOMAIN_FACT = Domain.FACT - -DIRECTIVE = Domain.DIRECTIVE - - -def domain_error_for_flag_values( - context: ExecutionContext, - procedure: Signature, - flag_values: Iterable[Term], - actual: Term, - index: int = None -) -> DomainError: - return DomainError.forFlagValues(context, procedure, flag_values, actual, index) - - -def domain_error_for_argument( - context: ExecutionContext, - procedure: Signature, - expected: Domain, - actual: Term, - index: int = None -) -> DomainError: - return DomainError.forArgument(context, procedure, expected, actual, index) - - -def domain_error_for_term( - context: ExecutionContext, - expected: Domain, - actual_value: Term, -) -> DomainError: - return DomainError.forTerm(context, expected, actual_value) - - -def domain_error_for_goal( - context: ExecutionContext, - procedure: Signature, - expected: Domain, - actual: Term, -) -> DomainError: - return DomainError.forGoal(context, procedure, expected, actual) - - -def domain(name: Union[str, Term]) -> Domain: - if isinstance(name, str): - return Domain.of(name) - else: - return Domain.fromTerm(name) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.DomainError.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/exception/error/domain/_api.py b/tuprolog/solve/exception/error/domain/_api.py new file mode 100644 index 0000000..ce87447 --- /dev/null +++ b/tuprolog/solve/exception/error/domain/_api.py @@ -0,0 +1,48 @@ +from typing import Iterable, Union +from tuprolog.core import Term +from tuprolog.solve import ExecutionContext, Signature +from ._definitions import DomainError, Domain + + +def domain_error_for_flag_values( + context: ExecutionContext, + procedure: Signature, + flag_values: Iterable[Term], + actual: Term, + index: int = None +) -> DomainError: + return DomainError.forFlagValues(context, procedure, flag_values, actual, index) + + +def domain_error_for_argument( + context: ExecutionContext, + procedure: Signature, + expected: Domain, + actual: Term, + index: int = None +) -> DomainError: + return DomainError.forArgument(context, procedure, expected, actual, index) + + +def domain_error_for_term( + context: ExecutionContext, + expected: Domain, + actual_value: Term, +) -> DomainError: + return DomainError.forTerm(context, expected, actual_value) + + +def domain_error_for_goal( + context: ExecutionContext, + procedure: Signature, + expected: Domain, + actual: Term, +) -> DomainError: + return DomainError.forGoal(context, procedure, expected, actual) + + +def domain(name: Union[str, Term]) -> Domain: + if isinstance(name, str): + return Domain.of(name) + else: + return Domain.fromTerm(name) diff --git a/tuprolog/solve/exception/error/domain/_definitions.py b/tuprolog/solve/exception/error/domain/_definitions.py new file mode 100644 index 0000000..31aeb20 --- /dev/null +++ b/tuprolog/solve/exception/error/domain/_definitions.py @@ -0,0 +1,129 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as errors # type: ignore + + +DomainError = errors.DomainError + + +Domain = DomainError.Expected + + +DOMAIN_wATOM_PROPERTY = Domain.ATOM_PROPERTY + + +DOMAIN_BUFFERING_MODE = Domain.BUFFERING_MODE + + +DOMAIN_CHARACTER_CODE_LIST = Domain.CHARACTER_CODE_LIST + + +DOMAIN_CLOSE_OPTION = Domain.CLOSE_OPTION + + +DOMAIN_DATE_TIME = Domain.DATE_TIME + + +DOMAIN_EOF_ACTION = Domain.EOF_ACTION + + +DOMAIN_FLAG_VALUE = Domain.FLAG_VALUE + + +DOMAIN_FORMAT_CONTROL_SEQUENCE = Domain.FORMAT_CONTROL_SEQUENCE + + +DOMAIN_IO_MODE = Domain.IO_MODE + + +DOMAIN_WELL_FORMED_LIST = Domain.WELL_FORMED_LIST + + +DOMAIN_NON_EMPTY_LIST = Domain.NON_EMPTY_LIST + + +DOMAIN_NOT_LESS_THAN_ZERO = Domain.NOT_LESS_THAN_ZERO + + +DOMAIN_OPERATOR_PRIORITY = Domain.OPERATOR_PRIORITY + + +DOMAIN_OPERATOR_SPECIFIER = Domain.OPERATOR_SPECIFIER + + +DOMAIN_ORDER = Domain.ORDER + + +DOMAIN_OS_FILE_PERMISSION = Domain.OS_FILE_PERMISSION + + +DOMAIN_OS_FILE_PROPERTY = Domain.OS_FILE_PROPERTY + + +DOMAIN_OS_PATH = Domain.OS_PATH + + +DOMAIN_PREDICATE_PROPERTY = Domain.PREDICATE_PROPERTY + + +DOMAIN_FLAG = Domain.FLAG + + +DOMAIN_READ_OPTION = Domain.READ_OPTION + + +DOMAIN_SELECTABLE_ITEM = Domain.SELECTABLE_ITEM + + +DOMAIN_SOCKET_ADDRESS = Domain.SOCKET_ADDRESS + + +DOMAIN_SOCKET_DOMAIN = Domain.SOCKET_DOMAIN + + +DOMAIN_SOURCE_SINK = Domain.SOURCE_SINK + + +DOMAIN_STREAM = Domain.STREAM + + +DOMAIN_STREAM_OPTION = Domain.STREAM_OPTION + + +DOMAIN_STREAM_OR_ALIAS = Domain.STREAM_OR_ALIAS + + +DOMAIN_STREAM_POSITION = Domain.STREAM_POSITION + + +DOMAIN_STREAM_PROPERTY = Domain.STREAM_PROPERTY + + +DOMAIN_STREAM_SEEK_METHOD = Domain.STREAM_SEEK_METHOD + + +DOMAIN_STREAM_TYPE = Domain.STREAM_TYPE + + +DOMAIN_TERM_STREAM_OR_ALIAS = Domain.TERM_STREAM_OR_ALIAS + + +DOMAIN_VAR_BINDING_OPTION = Domain.VAR_BINDING_OPTION + + +DOMAIN_WRITE_OPTION = Domain.WRITE_OPTION + + +DOMAIN_CLAUSE = Domain.CLAUSE + + +DOMAIN_RULE = Domain.RULE + + +DOMAIN_FACT = Domain.FACT + + +DIRECTIVE = Domain.DIRECTIVE + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.DomainError.*") diff --git a/tuprolog/solve/exception/error/evaluation/__init__.py b/tuprolog/solve/exception/error/evaluation/__init__.py index f2ed1c7..3272497 100644 --- a/tuprolog/solve/exception/error/evaluation/__init__.py +++ b/tuprolog/solve/exception/error/evaluation/__init__.py @@ -1,38 +1,2 @@ -from typing import Union -from tuprolog import logger -from tuprolog.core import Term, atom -from tuprolog.solve import ExecutionContext -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.exception.error as errors # type: ignore - -EvaluationError = errors.EvaluationError - -ErrorType = EvaluationError.Type - -ERROR_INT_OVERFLOW = ErrorType.INT_OVERFLOW - -ERROR_FLOAT_OVERFLOW = ErrorType.FLOAT_OVERFLOW - -ERROR_UNDERFLOW = ErrorType.UNDERFLOW - -ERROR_ZERO_DIVISOR = ErrorType.ZERO_DIVISOR - -ERROR_UNDEFINED = ErrorType.UNDEFINED - - -def evaluation_error( - context: ExecutionContext, - type: ErrorType, - message: str -) -> EvaluationError: - return EvaluationError(message, None, context, type, atom(message)) - - -def error_type(name: Union[str, Term]) -> ErrorType: - if isinstance(name, str): - return ErrorType.valueOf(name) - else: - return ErrorType.fromTerm(name) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.EvaluationError.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/exception/error/evaluation/_api.py b/tuprolog/solve/exception/error/evaluation/_api.py new file mode 100644 index 0000000..06463ee --- /dev/null +++ b/tuprolog/solve/exception/error/evaluation/_api.py @@ -0,0 +1,19 @@ +from typing import Union +from tuprolog.core import Term, atom +from tuprolog.solve import ExecutionContext +from ._definitions import EvaluationError, ErrorType + + +def evaluation_error( + context: ExecutionContext, + type: ErrorType, + message: str +) -> EvaluationError: + return EvaluationError(message, None, context, type, atom(message)) + + +def error_type(name: Union[str, Term]) -> ErrorType: + if isinstance(name, str): + return ErrorType.valueOf(name) + else: + return ErrorType.fromTerm(name) diff --git a/tuprolog/solve/exception/error/evaluation/_definitions.py b/tuprolog/solve/exception/error/evaluation/_definitions.py new file mode 100644 index 0000000..3715b89 --- /dev/null +++ b/tuprolog/solve/exception/error/evaluation/_definitions.py @@ -0,0 +1,27 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as errors # type: ignore + + +EvaluationError = errors.EvaluationError + + +ErrorType = EvaluationError.Type + + +ERROR_INT_OVERFLOW = ErrorType.INT_OVERFLOW + + +ERROR_FLOAT_OVERFLOW = ErrorType.FLOAT_OVERFLOW + + +ERROR_UNDERFLOW = ErrorType.UNDERFLOW + + +ERROR_ZERO_DIVISOR = ErrorType.ZERO_DIVISOR + + +ERROR_UNDEFINED = ErrorType.UNDEFINED + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.EvaluationError.*") diff --git a/tuprolog/solve/exception/error/existence/__init__.py b/tuprolog/solve/exception/error/existence/__init__.py index c34a236..3272497 100644 --- a/tuprolog/solve/exception/error/existence/__init__.py +++ b/tuprolog/solve/exception/error/existence/__init__.py @@ -1,73 +1,2 @@ -from typing import Union -from tuprolog import logger -from tuprolog.core import Term, Atom -from tuprolog.solve import ExecutionContext, Signature -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.exception.error as errors # type: ignore - -ExistenceError = errors.ExistenceError - -ObjectType = ExistenceError.ObjectType - -OBJECT_PROCEDURE = ObjectType.PROCEDURE - -OBJECT_SOURCE_SINK = ObjectType.SOURCE_SINK - -OBJECT_RESOURCE = ObjectType.RESOURCE - -OBJECT_STREAM = ObjectType.STREAM - -OBJECT_OOP_ALIAS = ObjectType.OOP_ALIAS - -OBJECT_OOP_METHOD = ObjectType.OOP_METHOD - -OBJECT_OOP_CONSTRUCTOR = ObjectType.OOP_CONSTRUCTOR - -OBJECT_OOP_PROPERTY = ObjectType.OOP_PROPERTY - - -def existence_error( - context: ExecutionContext, - type: ObjectType, - culprit: Term, - message: str -) -> ExistenceError: - return ExistenceError.of(context, type, culprit, message) - - -def existence_error_for_source_sink( - context: ExecutionContext, - alias: Union[Atom, str] -) -> ExistenceError: - return ExistenceError.forSourceSink(context, alias) - - -def existence_error_for_procedure( - context: ExecutionContext, - procedure: Signature -) -> ExistenceError: - return ExistenceError.forProcedure(context, procedure) - - -def existence_error_for_stream( - context: ExecutionContext, - stream: Term -) -> ExistenceError: - return ExistenceError.forStream(context, stream) - - -def existence_error_for_resource( - context: ExecutionContext, - name: str -) -> ExistenceError: - return ExistenceError.forResource(context, name) - - -def object_type(name: Union[str, Term]) -> ObjectType: - if isinstance(name, str): - return ObjectType.of(name) - else: - return ObjectType.fromTerm(name) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.ExistenceError.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/exception/error/existence/_api.py b/tuprolog/solve/exception/error/existence/_api.py new file mode 100644 index 0000000..adcfd9e --- /dev/null +++ b/tuprolog/solve/exception/error/existence/_api.py @@ -0,0 +1,48 @@ +from typing import Union +from tuprolog.core import Term, Atom +from tuprolog.solve import ExecutionContext, Signature +from ._definitions import ExistenceError, ObjectType + + +def existence_error( + context: ExecutionContext, + type: ObjectType, + culprit: Term, + message: str +) -> ExistenceError: + return ExistenceError.of(context, type, culprit, message) + + +def existence_error_for_source_sink( + context: ExecutionContext, + alias: Union[Atom, str] +) -> ExistenceError: + return ExistenceError.forSourceSink(context, alias) + + +def existence_error_for_procedure( + context: ExecutionContext, + procedure: Signature +) -> ExistenceError: + return ExistenceError.forProcedure(context, procedure) + + +def existence_error_for_stream( + context: ExecutionContext, + stream: Term +) -> ExistenceError: + return ExistenceError.forStream(context, stream) + + +def existence_error_for_resource( + context: ExecutionContext, + name: str +) -> ExistenceError: + return ExistenceError.forResource(context, name) + + +def object_type(name: Union[str, Term]) -> ObjectType: + if isinstance(name, str): + return ObjectType.of(name) + else: + return ObjectType.fromTerm(name) diff --git a/tuprolog/solve/exception/error/existence/_definitions.py b/tuprolog/solve/exception/error/existence/_definitions.py new file mode 100644 index 0000000..13cccf0 --- /dev/null +++ b/tuprolog/solve/exception/error/existence/_definitions.py @@ -0,0 +1,36 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as errors # type: ignore + + +ExistenceError = errors.ExistenceError + + +ObjectType = ExistenceError.ObjectType + + +OBJECT_PROCEDURE = ObjectType.PROCEDURE + + +OBJECT_SOURCE_SINK = ObjectType.SOURCE_SINK + + +OBJECT_RESOURCE = ObjectType.RESOURCE + + +OBJECT_STREAM = ObjectType.STREAM + + +OBJECT_OOP_ALIAS = ObjectType.OOP_ALIAS + + +OBJECT_OOP_METHOD = ObjectType.OOP_METHOD + + +OBJECT_OOP_CONSTRUCTOR = ObjectType.OOP_CONSTRUCTOR + + +OBJECT_OOP_PROPERTY = ObjectType.OOP_PROPERTY + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.ExistenceError.*") diff --git a/tuprolog/solve/exception/error/instantiation/__init__.py b/tuprolog/solve/exception/error/instantiation/__init__.py index 7056b92..3272497 100644 --- a/tuprolog/solve/exception/error/instantiation/__init__.py +++ b/tuprolog/solve/exception/error/instantiation/__init__.py @@ -1,28 +1,2 @@ -from tuprolog import logger -from tuprolog.core import Var -from tuprolog.solve import ExecutionContext, Signature -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore - - -InstantiationError = _errors.InstantiationError - - -def instantiation_error_for_argument( - context: ExecutionContext, - procedure: Signature, - variable: Var, - index: int = None -) -> InstantiationError: - return InstantiationError.forArgument(context, procedure, variable, index) - - -def instantiation_error_for_goal( - context: ExecutionContext, - procedure: Signature, - variable: Var -) -> InstantiationError: - return InstantiationError.forGoal(context, procedure, variable) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.InstantiationError.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/exception/error/instantiation/_api.py b/tuprolog/solve/exception/error/instantiation/_api.py new file mode 100644 index 0000000..51e5817 --- /dev/null +++ b/tuprolog/solve/exception/error/instantiation/_api.py @@ -0,0 +1,20 @@ +from tuprolog.core import Var +from tuprolog.solve import ExecutionContext, Signature +from ._definitions import InstantiationError + + +def instantiation_error_for_argument( + context: ExecutionContext, + procedure: Signature, + variable: Var, + index: int = None +) -> InstantiationError: + return InstantiationError.forArgument(context, procedure, variable, index) + + +def instantiation_error_for_goal( + context: ExecutionContext, + procedure: Signature, + variable: Var +) -> InstantiationError: + return InstantiationError.forGoal(context, procedure, variable) diff --git a/tuprolog/solve/exception/error/instantiation/_definitions.py b/tuprolog/solve/exception/error/instantiation/_definitions.py new file mode 100644 index 0000000..0899c55 --- /dev/null +++ b/tuprolog/solve/exception/error/instantiation/_definitions.py @@ -0,0 +1,9 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore + + +InstantiationError = _errors.InstantiationError + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.InstantiationError.*") diff --git a/tuprolog/solve/exception/error/message/__init__.py b/tuprolog/solve/exception/error/message/__init__.py index c8549aa..3272497 100644 --- a/tuprolog/solve/exception/error/message/__init__.py +++ b/tuprolog/solve/exception/error/message/__init__.py @@ -1,15 +1,2 @@ -from tuprolog import logger -from tuprolog.core import Term -from tuprolog.solve import ExecutionContext -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore - - -MessageError = _errors.MessageError - - -def message_error(content: Term, context: ExecutionContext, cause=None) -> MessageError: - return MessageError.of(content, context, cause) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.MessageError.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/exception/error/message/_api.py b/tuprolog/solve/exception/error/message/_api.py new file mode 100644 index 0000000..778f800 --- /dev/null +++ b/tuprolog/solve/exception/error/message/_api.py @@ -0,0 +1,7 @@ +from tuprolog.core import Term +from tuprolog.solve import ExecutionContext +from ._definitions import MessageError + + +def message_error(content: Term, context: ExecutionContext, cause=None) -> MessageError: + return MessageError.of(content, context, cause) diff --git a/tuprolog/solve/exception/error/message/_definitions.py b/tuprolog/solve/exception/error/message/_definitions.py new file mode 100644 index 0000000..5f42580 --- /dev/null +++ b/tuprolog/solve/exception/error/message/_definitions.py @@ -0,0 +1,9 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore + + +MessageError = _errors.MessageError + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.MessageError.*") diff --git a/tuprolog/solve/exception/error/permission/__init__.py b/tuprolog/solve/exception/error/permission/__init__.py index 11a9f65..3272497 100644 --- a/tuprolog/solve/exception/error/permission/__init__.py +++ b/tuprolog/solve/exception/error/permission/__init__.py @@ -1,80 +1,2 @@ -from typing import Union -from tuprolog import logger -from tuprolog.core import Term -from tuprolog.solve import ExecutionContext, Signature -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore - - -PermissionError = _errors.PermissionError - -Operation = PermissionError.Operation - -Permission = PermissionError.Permission - -OPERATION_ACCESS = Operation.ACCESS - -OPERATION_ADD_ALIAS = Operation.ADD_ALIAS - -OPERATION_CLOSE = Operation.CLOSE - -OPERATION_CREATE = Operation.CREATE - -OPERATION_INPUT = Operation.INPUT - -OPERATION_INVOKE = Operation.INVOKE - -OPERATION_MODIFY = Operation.MODIFY - -OPERATION_OPEN = Operation.OPEN - -OPERATION_OUTPUT = Operation.OUTPUT - -OPERATION_REPOSITION = Operation.REPOSITION - -PERMISSION_BINARY_STREAM = Permission.BINARY_STREAM - -PERMISSION_FLAG = Permission.FLAG - -PERMISSION_OPERATOR = Permission.OPERATOR - -PERMISSION_PAST_END_OF_STREAM = Permission.PAST_END_OF_STREAM - -PERMISSION_PRIVATE_PROCEDURE = Permission.PRIVATE_PROCEDURE - -PERMISSION_SOURCE_SINK = Permission.SOURCE_SINK - -PERMISSION_STATIC_PROCEDURE = Permission.STATIC_PROCEDURE - -PERMISSION_OOP_METHOD = Permission.OOP_METHOD - -PERMISSION_STREAM = Permission.STREAM - -PERMISSION_TEXT_STREAM = Permission.TEXT_STREAM - - -def permission_error( - context: ExecutionContext, - procedure: Signature, - operation: Operation, - permission: Permission, - culprit: Term -) -> PermissionError: - return PermissionError.of(context, procedure, operation, permission, culprit) - - -def operation(name: Union[str, Term]) -> Operation: - if isinstance(name, str): - return Operation.of(name) - else: - return Operation.fromTerm(name) - - -def permission(name: Union[str, Term]) -> Permission: - if isinstance(name, str): - return Permission.of(name) - else: - return Permission.fromTerm(name) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.PermissionError.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/exception/error/permission/_api.py b/tuprolog/solve/exception/error/permission/_api.py new file mode 100644 index 0000000..03b4819 --- /dev/null +++ b/tuprolog/solve/exception/error/permission/_api.py @@ -0,0 +1,28 @@ +from typing import Union +from tuprolog.core import Term +from tuprolog.solve import ExecutionContext, Signature +from ._definitions import PermissionError, Operation, Permission + + +def permission_error( + context: ExecutionContext, + procedure: Signature, + operation: Operation, + permission: Permission, + culprit: Term +) -> PermissionError: + return PermissionError.of(context, procedure, operation, permission, culprit) + + +def operation(name: Union[str, Term]) -> Operation: + if isinstance(name, str): + return Operation.of(name) + else: + return Operation.fromTerm(name) + + +def permission(name: Union[str, Term]) -> Permission: + if isinstance(name, str): + return Permission.of(name) + else: + return Permission.fromTerm(name) diff --git a/tuprolog/solve/exception/error/permission/_definitions.py b/tuprolog/solve/exception/error/permission/_definitions.py new file mode 100644 index 0000000..5295c49 --- /dev/null +++ b/tuprolog/solve/exception/error/permission/_definitions.py @@ -0,0 +1,75 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore + + +PermissionError = _errors.PermissionError + + +Operation = PermissionError.Operation + + +Permission = PermissionError.Permission + + +OPERATION_ACCESS = Operation.ACCESS + + +OPERATION_ADD_ALIAS = Operation.ADD_ALIAS + + +OPERATION_CLOSE = Operation.CLOSE + + +OPERATION_CREATE = Operation.CREATE + + +OPERATION_INPUT = Operation.INPUT + + +OPERATION_INVOKE = Operation.INVOKE + + +OPERATION_MODIFY = Operation.MODIFY + + +OPERATION_OPEN = Operation.OPEN + + +OPERATION_OUTPUT = Operation.OUTPUT + + +OPERATION_REPOSITION = Operation.REPOSITION + + +PERMISSION_BINARY_STREAM = Permission.BINARY_STREAM + + +PERMISSION_FLAG = Permission.FLAG + + +PERMISSION_OPERATOR = Permission.OPERATOR + + +PERMISSION_PAST_END_OF_STREAM = Permission.PAST_END_OF_STREAM + + +PERMISSION_PRIVATE_PROCEDURE = Permission.PRIVATE_PROCEDURE + + +PERMISSION_SOURCE_SINK = Permission.SOURCE_SINK + + +PERMISSION_STATIC_PROCEDURE = Permission.STATIC_PROCEDURE + + +PERMISSION_OOP_METHOD = Permission.OOP_METHOD + + +PERMISSION_STREAM = Permission.STREAM + + +PERMISSION_TEXT_STREAM = Permission.TEXT_STREAM + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.PermissionError.*") diff --git a/tuprolog/solve/exception/error/representation/__init__.py b/tuprolog/solve/exception/error/representation/__init__.py index 609c084..3272497 100644 --- a/tuprolog/solve/exception/error/representation/__init__.py +++ b/tuprolog/solve/exception/error/representation/__init__.py @@ -1,45 +1,2 @@ -from typing import Union -from tuprolog import logger -from tuprolog.core import Term -from tuprolog.solve import ExecutionContext, Signature -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore - -RepresentationError = _errors.RepresentationError - -Limit = RepresentationError.Limit - -LIMIT_CHARACTER = Limit.CHARACTER - -LIMIT_CHARACTER_CODE = Limit.CHARACTER_CODE - -LIMIT_IN_CHARACTER_CODE = Limit.IN_CHARACTER_CODE - -LIMIT_MAX_ARITY = Limit.MAX_ARITY - -LIMIT_MAX_INTEGER = Limit.MAX_INTEGER - -LIMIT_MIN_INTEGER = Limit.MIN_INTEGER - -LIMIT_OOP_OBJECT = Limit.OOP_OBJECT - -LIMIT_TOO_MANY_VARIABLES = Limit.TOO_MANY_VARIABLES - - -def representation_error( - context: ExecutionContext, - procedure: Signature, - limit: Limit, - cause=None -) -> RepresentationError: - return RepresentationError.of(context, procedure, limit, cause) - - -def limit(name: Union[str, Term]) -> Limit: - if isinstance(name, str): - return Limit.of(name) - else: - return Limit.fromTerm(name) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.RepresentationError.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/exception/error/representation/_api.py b/tuprolog/solve/exception/error/representation/_api.py new file mode 100644 index 0000000..f97754a --- /dev/null +++ b/tuprolog/solve/exception/error/representation/_api.py @@ -0,0 +1,20 @@ +from typing import Union +from tuprolog.core import Term +from tuprolog.solve import ExecutionContext, Signature +from ._definitions import RepresentationError, Limit + + +def representation_error( + context: ExecutionContext, + procedure: Signature, + limit: Limit, + cause=None +) -> RepresentationError: + return RepresentationError.of(context, procedure, limit, cause) + + +def limit(name: Union[str, Term]) -> Limit: + if isinstance(name, str): + return Limit.of(name) + else: + return Limit.fromTerm(name) diff --git a/tuprolog/solve/exception/error/representation/_definitions.py b/tuprolog/solve/exception/error/representation/_definitions.py new file mode 100644 index 0000000..9fd90eb --- /dev/null +++ b/tuprolog/solve/exception/error/representation/_definitions.py @@ -0,0 +1,36 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore + + +RepresentationError = _errors.RepresentationError + + +Limit = RepresentationError.Limit + + +LIMIT_CHARACTER = Limit.CHARACTER + + +LIMIT_CHARACTER_CODE = Limit.CHARACTER_CODE + + +LIMIT_IN_CHARACTER_CODE = Limit.IN_CHARACTER_CODE + + +LIMIT_MAX_ARITY = Limit.MAX_ARITY + + +LIMIT_MAX_INTEGER = Limit.MAX_INTEGER + + +LIMIT_MIN_INTEGER = Limit.MIN_INTEGER + + +LIMIT_OOP_OBJECT = Limit.OOP_OBJECT + + +LIMIT_TOO_MANY_VARIABLES = Limit.TOO_MANY_VARIABLES + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.RepresentationError.*") diff --git a/tuprolog/solve/exception/error/syntax/__init__.py b/tuprolog/solve/exception/error/syntax/__init__.py index 35c9450..3272497 100644 --- a/tuprolog/solve/exception/error/syntax/__init__.py +++ b/tuprolog/solve/exception/error/syntax/__init__.py @@ -1,42 +1,2 @@ -from tuprolog import logger -from tuprolog.solve import ExecutionContext -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore - - -SyntaxError = _errors.SyntaxError - - -def syntax_error( - context: ExecutionContext, - message: str -) -> SyntaxError: - return SyntaxError.of(context, message) - - -def syntax_error_while_parsing_term( - context: ExecutionContext, - input: str, - row: int, - column: int, - message: str -) -> SyntaxError: - return SyntaxError.whileParsingTerm(context, input, row, column, message) - - -def syntax_error_while_parsing_clauses( - context: ExecutionContext, - input: str, - index: int, - row: int, - column: int, - message: str -) -> SyntaxError: - return SyntaxError.whileParsingClauses(context, input, index, row, column, message) - - -def error_detector(text: str, line: int, column: int, message: str = None) -> str: - return SyntaxError.errorDetector(text, line, column, message) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.SyntaxError.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/exception/error/syntax/_api.py b/tuprolog/solve/exception/error/syntax/_api.py new file mode 100644 index 0000000..00b463e --- /dev/null +++ b/tuprolog/solve/exception/error/syntax/_api.py @@ -0,0 +1,34 @@ +from tuprolog.solve import ExecutionContext +from ._definitions import SyntaxError + + +def syntax_error( + context: ExecutionContext, + message: str +) -> SyntaxError: + return SyntaxError.of(context, message) + + +def syntax_error_while_parsing_term( + context: ExecutionContext, + input: str, + row: int, + column: int, + message: str +) -> SyntaxError: + return SyntaxError.whileParsingTerm(context, input, row, column, message) + + +def syntax_error_while_parsing_clauses( + context: ExecutionContext, + input: str, + index: int, + row: int, + column: int, + message: str +) -> SyntaxError: + return SyntaxError.whileParsingClauses(context, input, index, row, column, message) + + +def error_detector(text: str, line: int, column: int, message: str = None) -> str: + return SyntaxError.errorDetector(text, line, column, message) diff --git a/tuprolog/solve/exception/error/syntax/_definitions.py b/tuprolog/solve/exception/error/syntax/_definitions.py new file mode 100644 index 0000000..1da6a1a --- /dev/null +++ b/tuprolog/solve/exception/error/syntax/_definitions.py @@ -0,0 +1,9 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore + + +SyntaxError = _errors.SyntaxError + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.SyntaxError.*") diff --git a/tuprolog/solve/exception/error/system/__init__.py b/tuprolog/solve/exception/error/system/__init__.py index 13b8a5c..3272497 100644 --- a/tuprolog/solve/exception/error/system/__init__.py +++ b/tuprolog/solve/exception/error/system/__init__.py @@ -1,17 +1,2 @@ -from tuprolog import logger -from tuprolog.solve import ExecutionContext -from tuprolog.solve.exception import LogicError -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore - - -SystemError = _errors.SyntaxError - - -def syntax_error(context: ExecutionContext, message: str, exception) -> SystemError: - if isinstance(exception, LogicError): - return SystemError.forUncaughtError(context, message, exception) - return SystemError.forUncaughtException(context, message, exception) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.SystemError.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/exception/error/system/_api.py b/tuprolog/solve/exception/error/system/_api.py new file mode 100644 index 0000000..44fc0ba --- /dev/null +++ b/tuprolog/solve/exception/error/system/_api.py @@ -0,0 +1,9 @@ +from tuprolog.solve import ExecutionContext +from tuprolog.solve.exception import LogicError +from ._definitions import SystemError + + +def syntax_error(context: ExecutionContext, message: str, exception) -> SystemError: + if isinstance(exception, LogicError): + return SystemError.forUncaughtError(context, message, exception) + return SystemError.forUncaughtException(context, message, exception) diff --git a/tuprolog/solve/exception/error/system/_definitions.py b/tuprolog/solve/exception/error/system/_definitions.py new file mode 100644 index 0000000..cba43ab --- /dev/null +++ b/tuprolog/solve/exception/error/system/_definitions.py @@ -0,0 +1,9 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore + + +SystemError = _errors.SyntaxError + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.SystemError.*") diff --git a/tuprolog/solve/exception/error/type/__init__.py b/tuprolog/solve/exception/error/type/__init__.py index 4cfe91a..3272497 100644 --- a/tuprolog/solve/exception/error/type/__init__.py +++ b/tuprolog/solve/exception/error/type/__init__.py @@ -1,132 +1,2 @@ -from typing import Union -from tuprolog import logger -from tuprolog.core import Term -from tuprolog.solve import ExecutionContext, Signature -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore - - -TypeError = _errors.TypeError - - -Type = TypeError.Expected - - -TYPE_ATOM = Type.ATOM - - -TYPE_ATOMIC = Type.ATOMIC - - -TYPE_BOOLEAN = Type.BOOLEAN - - -TYPE_BYTE = Type.BYTE - - -TYPE_CALLABLE = Type.CALLABLE - - -TYPE_CHARACTER = Type.CHARACTER - - -TYPE_COMPOUND = Type.COMPOUND - - -TYPE_DEALIASING_EXPRESSION = Type.DEALIASING_EXPRESSION - - -TYPE_EVALUABLE = Type.EVALUABLE - - -TYPE_FLOAT = Type.FLOAT - - -TYPE_INTEGER = Type.INTEGER - - -TYPE_IN_CHARACTER = Type.IN_CHARACTER - - -TYPE_LIST = Type.LIST - - -TYPE_NUMBER = Type.NUMBER - - -TYPE_OBJECT_REFERENCE = Type.OBJECT_REFERENCE - - -TYPE_PAIR = Type.PAIR - - -TYPE_PREDICATE_INDICATOR = Type.PREDICATE_INDICATOR - - -TYPE_REFERENCE = Type.REFERENCE - - -TYPE_TYPE_REFERENCE = Type.TYPE_REFERENCE - - -TYPE_URL = Type.URL - - -TYPE_VARIABLE = Type.VARIABLE - - -def type_error_for_flag_values( - context: ExecutionContext, - procedure: Signature, - expected: Type, - actual: Term, - message: str -) -> TypeError: - return TypeError.of(context, procedure, expected, actual, message) - - -def type_error_for_argument_list( - context: ExecutionContext, - procedure: Signature, - expected: Type, - actual: Term, - index: int = None -) -> TypeError: - return TypeError.forArgumentList(context, procedure, expected, actual, index) - - -def type_error_for_argument( - context: ExecutionContext, - procedure: Signature, - expected: Type, - actual: Term, - index: int = None -) -> TypeError: - return TypeError.forArgument(context, procedure, expected, actual, index) - - -def type_error_for_term( - context: ExecutionContext, - expected: Type, - actual_value: Term, -) -> TypeError: - return TypeError.forTerm(context, expected, actual_value) - - -def type_error_for_goal( - context: ExecutionContext, - procedure: Signature, - expected: Type, - actual: Term, -) -> TypeError: - return TypeError.forGoal(context, procedure, expected, actual) - - -def type(name: Union[str, Term]) -> Type: - if isinstance(name, str): - return TypeError.valueOf(name) - else: - return TypeError.fromTerm(name) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.TypeError.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/exception/error/type/_api.py b/tuprolog/solve/exception/error/type/_api.py new file mode 100644 index 0000000..41f4831 --- /dev/null +++ b/tuprolog/solve/exception/error/type/_api.py @@ -0,0 +1,58 @@ +from typing import Union +from tuprolog.core import Term +from tuprolog.solve import ExecutionContext, Signature +from ._definitions import TypeError, Type + + +def type_error_for_flag_values( + context: ExecutionContext, + procedure: Signature, + expected: Type, + actual: Term, + message: str +) -> TypeError: + return TypeError.of(context, procedure, expected, actual, message) + + +def type_error_for_argument_list( + context: ExecutionContext, + procedure: Signature, + expected: Type, + actual: Term, + index: int = None +) -> TypeError: + return TypeError.forArgumentList(context, procedure, expected, actual, index) + + +def type_error_for_argument( + context: ExecutionContext, + procedure: Signature, + expected: Type, + actual: Term, + index: int = None +) -> TypeError: + return TypeError.forArgument(context, procedure, expected, actual, index) + + +def type_error_for_term( + context: ExecutionContext, + expected: Type, + actual_value: Term, +) -> TypeError: + return TypeError.forTerm(context, expected, actual_value) + + +def type_error_for_goal( + context: ExecutionContext, + procedure: Signature, + expected: Type, + actual: Term, +) -> TypeError: + return TypeError.forGoal(context, procedure, expected, actual) + + +def type(name: Union[str, Term]) -> Type: + if isinstance(name, str): + return TypeError.valueOf(name) + else: + return TypeError.fromTerm(name) diff --git a/tuprolog/solve/exception/error/type/_definitions.py b/tuprolog/solve/exception/error/type/_definitions.py new file mode 100644 index 0000000..68676f0 --- /dev/null +++ b/tuprolog/solve/exception/error/type/_definitions.py @@ -0,0 +1,75 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.error as _errors # type: ignore + + +TypeError = _errors.TypeError + + +Type = TypeError.Expected + + +TYPE_ATOM = Type.ATOM + + +TYPE_ATOMIC = Type.ATOMIC + + +TYPE_BOOLEAN = Type.BOOLEAN + + +TYPE_BYTE = Type.BYTE + + +TYPE_CALLABLE = Type.CALLABLE + + +TYPE_CHARACTER = Type.CHARACTER + + +TYPE_COMPOUND = Type.COMPOUND + + +TYPE_DEALIASING_EXPRESSION = Type.DEALIASING_EXPRESSION + + +TYPE_EVALUABLE = Type.EVALUABLE + + +TYPE_FLOAT = Type.FLOAT + + +TYPE_INTEGER = Type.INTEGER + + +TYPE_IN_CHARACTER = Type.IN_CHARACTER + + +TYPE_LIST = Type.LIST + + +TYPE_NUMBER = Type.NUMBER + + +TYPE_OBJECT_REFERENCE = Type.OBJECT_REFERENCE + + +TYPE_PAIR = Type.PAIR + + +TYPE_PREDICATE_INDICATOR = Type.PREDICATE_INDICATOR + + +TYPE_REFERENCE = Type.REFERENCE + + +TYPE_TYPE_REFERENCE = Type.TYPE_REFERENCE + + +TYPE_URL = Type.URL + + +TYPE_VARIABLE = Type.VARIABLE + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.error.TypeError.*") diff --git a/tuprolog/solve/exception/warning/__init__.py b/tuprolog/solve/exception/warning/__init__.py index 939fe13..3272497 100644 --- a/tuprolog/solve/exception/warning/__init__.py +++ b/tuprolog/solve/exception/warning/__init__.py @@ -1,28 +1,2 @@ -from tuprolog import logger -from tuprolog.core import Struct -from tuprolog.solve import ExecutionContext, ResolutionException, Signature -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.exception.warning as _warnings # type: ignore - -InitializationIssue = _warnings.InitializationIssue - -MissingPredicate = _warnings.MissingPredicate - - -def initialization_issue( - goal: Struct, - context: ExecutionContext, - cause: ResolutionException = None -) -> InitializationIssue: - return InitializationIssue(goal, cause, context) - - -def missing_predicate( - signature: Signature, - context: ExecutionContext, - cause=None -) -> MissingPredicate: - return MissingPredicate(cause, context, signature) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.warning.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/exception/warning/_api.py b/tuprolog/solve/exception/warning/_api.py new file mode 100644 index 0000000..f3cd7ec --- /dev/null +++ b/tuprolog/solve/exception/warning/_api.py @@ -0,0 +1,19 @@ +from tuprolog.core import Struct +from tuprolog.solve import ExecutionContext, ResolutionException, Signature +from ._definitions import InitializationIssue, MissingPredicate + + +def initialization_issue( + goal: Struct, + context: ExecutionContext, + cause: ResolutionException = None +) -> InitializationIssue: + return InitializationIssue(goal, cause, context) + + +def missing_predicate( + signature: Signature, + context: ExecutionContext, + cause=None +) -> MissingPredicate: + return MissingPredicate(cause, context, signature) diff --git a/tuprolog/solve/exception/warning/_definitions.py b/tuprolog/solve/exception/warning/_definitions.py new file mode 100644 index 0000000..3d58fd8 --- /dev/null +++ b/tuprolog/solve/exception/warning/_definitions.py @@ -0,0 +1,12 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.exception.warning as _warnings # type: ignore + + +InitializationIssue = _warnings.InitializationIssue + + +MissingPredicate = _warnings.MissingPredicate + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.exception.warning.*") diff --git a/tuprolog/solve/flags/__init__.py b/tuprolog/solve/flags/__init__.py index c1b88a8..3272497 100644 --- a/tuprolog/solve/flags/__init__.py +++ b/tuprolog/solve/flags/__init__.py @@ -1,74 +1,2 @@ -from typing import Iterable, Union, Mapping -from tuprolog import logger -from tuprolog.core import Term -from tuprolog.jvmutils import kpair, jmap, jarray, Pair -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.flags as _flags # type: ignore - - -DoubleQuotes = _flags.DoubleQuotes - -FlagStore = _flags.FlagStore - -LastCallOptimization = _flags.LastCallOptimization - -MaxArity = _flags.MaxArity - -NotableFlag = _flags.NotableFlag - -Unknown = _flags.Unknown - -Flag = Pair - -EMPTY_FLAG_STORE: FlagStore = FlagStore.EMPTY - -DEFAULT_FLAG_STORE: FlagStore = FlagStore.DEFAULT - -DoubleQuotes: NotableFlag = DoubleQuotes.INSTANCE - -LastCallOptimization: NotableFlag = LastCallOptimization.INSTANCE - -MaxArity: NotableFlag = MaxArity.INSTANCE - -Unknown: NotableFlag = Unknown.INSTANCE - - -def flag(first: Union[str, NotableFlag, Iterable], value: Term = None) -> Flag: - if isinstance(first, NotableFlag): - if value is None: - return first.toPair() - else: - return first.to(value) - elif isinstance(first, str): - if value is None: - raise ValueError("Argument value is None") - return Flag(first, value) - elif isinstance(first, Iterable) and value is None: - return kpair(first) - else: - raise ValueError("Argument first is not iterable nor str") - - -def flag_store(*flags: Union[NotableFlag, Flag, Iterable, FlagStore], **kwargs: Mapping[str, Term]): - normal_flags = [] - notable_flags = [] - other_stores = [] - for f in flags: - if isinstance(f, NotableFlag): - notable_flags.append(f) - elif isinstance(f, Flag): - normal_flags.append(f) - elif isinstance(f, FlagStore): - other_stores.append(f) - else: - normal_flags.append(flag(f)) - store1 = FlagStore.of(jarray(NotableFlag)@notable_flags) - store2 = FlagStore.of(jarray(Flag)@normal_flags) - store3 = FlagStore.of(jmap(kwargs)) - store = store1.plus(store2).plus(store3) - for s in other_stores: - store = store.plus(s) - return store - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.flags.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/flags/_api.py b/tuprolog/solve/flags/_api.py new file mode 100644 index 0000000..3e3fdc7 --- /dev/null +++ b/tuprolog/solve/flags/_api.py @@ -0,0 +1,42 @@ +from typing import Iterable, Union, Mapping +from tuprolog.core import Term +from tuprolog.jvmutils import kpair, jmap, jarray +from ._definitions import FlagStore, NotableFlag, Flag + + +def flag(first: Union[str, NotableFlag, Iterable], value: Term = None) -> Flag: + if isinstance(first, NotableFlag): + if value is None: + return first.toPair() + else: + return first.to(value) + elif isinstance(first, str): + if value is None: + raise ValueError("Argument value is None") + return Flag(first, value) + elif isinstance(first, Iterable) and value is None: + return kpair(first) + else: + raise ValueError("Argument first is not iterable nor str") + + +def flag_store(*flags: Union[NotableFlag, Flag, Iterable, FlagStore], **kwargs: Mapping[str, Term]): + normal_flags = [] + notable_flags = [] + other_stores = [] + for f in flags: + if isinstance(f, NotableFlag): + notable_flags.append(f) + elif isinstance(f, Flag): + normal_flags.append(f) + elif isinstance(f, FlagStore): + other_stores.append(f) + else: + normal_flags.append(flag(f)) + store1 = FlagStore.of(jarray(NotableFlag)@notable_flags) + store2 = FlagStore.of(jarray(Flag)@normal_flags) + store3 = FlagStore.of(jmap(kwargs)) + store = store1.plus(store2).plus(store3) + for s in other_stores: + store = store.plus(s) + return store diff --git a/tuprolog/solve/flags/_definitions.py b/tuprolog/solve/flags/_definitions.py new file mode 100644 index 0000000..95f4869 --- /dev/null +++ b/tuprolog/solve/flags/_definitions.py @@ -0,0 +1,52 @@ +from tuprolog import logger +from tuprolog.jvmutils import Pair +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.flags as _flags # type: ignore + + +DoubleQuotes = _flags.DoubleQuotes + + +FlagStore = _flags.FlagStore + + +LastCallOptimization = _flags.LastCallOptimization + + +MaxArity = _flags.MaxArity + + +NotableFlag = _flags.NotableFlag + + +TrackVariables = _flags.TrackVariables + + +Unknown = _flags.Unknown + + +Flag = Pair + + +EMPTY_FLAG_STORE: FlagStore = FlagStore.EMPTY + + +DEFAULT_FLAG_STORE: FlagStore = FlagStore.DEFAULT + + +DoubleQuotes: NotableFlag = DoubleQuotes.INSTANCE + + +LastCallOptimization: NotableFlag = LastCallOptimization.INSTANCE + + +MaxArity: NotableFlag = MaxArity.INSTANCE + + +TrackVariables: NotableFlag = TrackVariables.INSTANCE + + +Unknown: NotableFlag = Unknown.INSTANCE + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.flags.*") diff --git a/tuprolog/solve/function/__init__.py b/tuprolog/solve/function/__init__.py index c9b5799..3272497 100644 --- a/tuprolog/solve/function/__init__.py +++ b/tuprolog/solve/function/__init__.py @@ -1,58 +1,2 @@ -from typing import List, Callable -from tuprolog import logger -from tuprolog.core import Term -from tuprolog.solve import ExecutionContext, Signature, current_time_instant, MAX_TIMEOUT -from tuprolog.solve.primitive import SolveRequest -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.function as _function # type: ignore - - -LogicFunction = _function.LogicFunction - -Compute = _function.Compute - -ArithmeticUtilsKt = _function.ArithmeticUtilsKt - -ComputeRequest = Compute.Request - -ComputeResponse = Compute.Request - - -@jpype.JImplements(LogicFunction) -class AbstractLogicFunction(object): - @jpype.JOverride - def compute(self, request: ComputeRequest) -> ComputeResponse: - raise NotImplementedError() - - -def logic_function(callable: Callable[[ComputeRequest], ComputeResponse]) -> LogicFunction: - class CallableToLogicFunctionAdapter(AbstractLogicFunction): - def compute(self, request: ComputeRequest) -> ComputeResponse: - return callable(request) - - return CallableToLogicFunctionAdapter() - - -def compute_request( - signature: Signature, - arguments: List[Term], - context: ExecutionContext, - issuing_instant: int = current_time_instant, - max_duration: int = MAX_TIMEOUT -) -> ComputeRequest: - return ComputeRequest(signature, arguments, context, issuing_instant, max_duration) - - -def compute_response(result: Term) -> ComputeResponse: - return ComputeResponse(result) - - -def eval_as_expression(term: Term, request: SolveRequest, index: int = None) -> Term: - return ArithmeticUtilsKt.evalAsExpression(term, request, index) - - -def eval_as_arithmetic_expression(term: Term, request: SolveRequest, index: int = None) -> Term: - return ArithmeticUtilsKt.evalAsArithmeticExpression(term, request, index) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.function.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/function/_api.py b/tuprolog/solve/function/_api.py new file mode 100644 index 0000000..52fd721 --- /dev/null +++ b/tuprolog/solve/function/_api.py @@ -0,0 +1,35 @@ +from typing import List, Callable +from tuprolog.core import Term +from tuprolog.solve import ExecutionContext, Signature, current_time_instant, MAX_TIMEOUT +from tuprolog.solve.primitive import SolveRequest +from ._definitions import LogicFunction, ArithmeticUtilsKt, ComputeRequest, ComputeResponse, AbstractLogicFunction + + +def logic_function(callable: Callable[[ComputeRequest], ComputeResponse]) -> LogicFunction: + class CallableToLogicFunctionAdapter(AbstractLogicFunction): + def compute(self, request: ComputeRequest) -> ComputeResponse: + return callable(request) + + return CallableToLogicFunctionAdapter() + + +def compute_request( + signature: Signature, + arguments: List[Term], + context: ExecutionContext, + issuing_instant: int = current_time_instant, + max_duration: int = MAX_TIMEOUT +) -> ComputeRequest: + return ComputeRequest(signature, arguments, context, issuing_instant, max_duration) + + +def compute_response(result: Term) -> ComputeResponse: + return ComputeResponse(result) + + +def eval_as_expression(term: Term, request: SolveRequest, index: int = None) -> Term: + return ArithmeticUtilsKt.evalAsExpression(term, request, index) + + +def eval_as_arithmetic_expression(term: Term, request: SolveRequest, index: int = None) -> Term: + return ArithmeticUtilsKt.evalAsArithmeticExpression(term, request, index) diff --git a/tuprolog/solve/function/_definitions.py b/tuprolog/solve/function/_definitions.py new file mode 100644 index 0000000..e5921d1 --- /dev/null +++ b/tuprolog/solve/function/_definitions.py @@ -0,0 +1,29 @@ +from jpype import JImplements, JOverride +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.function as _function # type: ignore + + +LogicFunction = _function.LogicFunction + + +Compute = _function.Compute + + +ArithmeticUtilsKt = _function.ArithmeticUtilsKt + + +ComputeRequest = Compute.Request + + +ComputeResponse = Compute.Request + + +@JImplements(LogicFunction) +class AbstractLogicFunction(object): + @JOverride + def compute(self, request: ComputeRequest) -> ComputeResponse: + raise NotImplementedError() + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.function.*") From ad4484a26ed026d4b3192179d2dd55dbbba3a22f Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 12 Oct 2023 12:54:46 +0200 Subject: [PATCH 131/154] Complete overhaul of solve package --- tuprolog/__main__.py | 6 +- tuprolog/solve/library/__init__.py | 59 +---- tuprolog/solve/library/_api.py | 45 ++++ tuprolog/solve/library/_definititions.py | 15 ++ .../{exception/__init__.py => exception.py} | 2 + tuprolog/solve/plp/__init__.py | 51 +---- tuprolog/solve/plp/_api.py | 41 ++++ tuprolog/solve/plp/_definitions.py | 9 + tuprolog/solve/primitive/__init__.py | 161 +------------ tuprolog/solve/primitive/_api.py | 136 +++++++++++ tuprolog/solve/primitive/_definitions.py | 30 +++ tuprolog/solve/sideffcts/__init__.py | 167 -------------- tuprolog/solve/sideffects/__init__.py | 2 + tuprolog/solve/sideffects/_api.py | 166 ++++++++++++++ tuprolog/solve/sideffects/_definitions.py | 99 ++++++++ tuprolog/solve/stdlib/__init__.py | 16 +- tuprolog/solve/stdlib/_definitions.py | 18 ++ .../{function/__init__.py => function.py} | 28 +++ tuprolog/solve/stdlib/magic.py | 9 + tuprolog/solve/stdlib/primitive.py | 214 ++++++++++++++++++ tuprolog/solve/stdlib/primitive/__init__.py | 145 ------------ tuprolog/solve/stdlib/rule.py | 73 ++++++ tuprolog/solve/stdlib/rule/__init__.py | 76 ------- 23 files changed, 896 insertions(+), 672 deletions(-) create mode 100644 tuprolog/solve/library/_api.py create mode 100644 tuprolog/solve/library/_definititions.py rename tuprolog/solve/library/{exception/__init__.py => exception.py} (99%) create mode 100644 tuprolog/solve/plp/_api.py create mode 100644 tuprolog/solve/plp/_definitions.py create mode 100644 tuprolog/solve/primitive/_api.py create mode 100644 tuprolog/solve/primitive/_definitions.py delete mode 100644 tuprolog/solve/sideffcts/__init__.py create mode 100644 tuprolog/solve/sideffects/__init__.py create mode 100644 tuprolog/solve/sideffects/_api.py create mode 100644 tuprolog/solve/sideffects/_definitions.py create mode 100644 tuprolog/solve/stdlib/_definitions.py rename tuprolog/solve/stdlib/{function/__init__.py => function.py} (98%) create mode 100644 tuprolog/solve/stdlib/magic.py create mode 100644 tuprolog/solve/stdlib/primitive.py delete mode 100644 tuprolog/solve/stdlib/primitive/__init__.py create mode 100644 tuprolog/solve/stdlib/rule.py delete mode 100644 tuprolog/solve/stdlib/rule/__init__.py diff --git a/tuprolog/__main__.py b/tuprolog/__main__.py index 283e19c..fd552e1 100644 --- a/tuprolog/__main__.py +++ b/tuprolog/__main__.py @@ -1,10 +1,8 @@ from tuprolog import Info from tuprolog.core import * -from tuprolog.core.comparators import * from tuprolog.core.exception import * from tuprolog.core.impl import * from tuprolog.core.operators import * -from tuprolog.core.visitors import * from tuprolog.core.parsing import * from tuprolog.unify import * from tuprolog.unify.exception import * @@ -18,7 +16,7 @@ from tuprolog.solve.flags import * from tuprolog.solve.function import * from tuprolog.solve.primitive import * -from tuprolog.solve.sideffcts import * +from tuprolog.solve.sideffects import * from tuprolog.solve.library import * from tuprolog.solve.library.exception import * from tuprolog.solve.data import * @@ -26,7 +24,7 @@ from tuprolog.solve.stdlib.primitive import * from tuprolog.solve.stdlib.rule import * from tuprolog.solve.stdlib.function import * -from tuprolog.solve.classic import * +from tuprolog.solve.stdlib.magic import * from tuprolog.solve.prolog import * from tuprolog.solve.plp import * from tuprolog.solve.problog import * diff --git a/tuprolog/solve/library/__init__.py b/tuprolog/solve/library/__init__.py index 1f1c2fd..e29704a 100644 --- a/tuprolog/solve/library/__init__.py +++ b/tuprolog/solve/library/__init__.py @@ -1,57 +1,2 @@ -from typing import Union, Mapping, Iterable -from functools import reduce -from tuprolog import logger -from tuprolog.core.operators import OperatorSet, operator_set -from tuprolog.theory import Theory, theory -from tuprolog.solve import Signature -from tuprolog.solve.primitive import Primitive -from tuprolog.solve.function import LogicFunction -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.library as _library # type: ignore - - -Library = _library.Library - -Pluggable = _library.Pluggable - -Runtime = _library.Runtime - - -def library( - alias: str = None, - primitives: Mapping[Signature, Primitive] = dict(), - theory: Theory = theory(), - operators: OperatorSet = operator_set(), - functions: Mapping[Signature, LogicFunction] = dict(), -) -> Union[Library, Pluggable]: - if alias is None: - return Library.of(primitives, theory.clauses, operators, functions) - else: - return Library.of(alias, primitives, theory.clauses, operators, functions) - - -def aliased(alias: str, library: Library) -> Library: - return Library.of(alias, library) - - -def libraries( - *libs: Union[Library, Iterable[Library]], - **kwargs: Library -) -> Library: - all_libraries = [] - queue = list(libs) - while len(queue) > 0: - current = queue.pop() - if isinstance(current, Library): - all_libraries.append(current) - elif isinstance(current, Iterable): - queue.extend(current) - else: - raise TypeError(f'Expected Library or Iterable[Library], got {type(current)}') - for alias, library in kwargs.items(): - if isinstance(library, Library): - all_libraries.append(aliased(alias, kwargs[alias])) - return reduce(lambda a, b: a.plus(b), all_libraries, Library.of({}, [], operator_set(), {})) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.library.*") +from ._definititions import * +from ._api import * diff --git a/tuprolog/solve/library/_api.py b/tuprolog/solve/library/_api.py new file mode 100644 index 0000000..6f5286d --- /dev/null +++ b/tuprolog/solve/library/_api.py @@ -0,0 +1,45 @@ +from typing import Union, Mapping, Iterable +from functools import reduce +from tuprolog.core.operators import OperatorSet, operator_set +from tuprolog.theory import Theory, theory +from tuprolog.solve import Signature +from tuprolog.solve.primitive import Primitive +from tuprolog.solve.function import LogicFunction +from ._definititions import Library, Pluggable + + +def library( + alias: str = None, + primitives: Mapping[Signature, Primitive] = dict(), + theory: Theory = theory(), + operators: OperatorSet = operator_set(), + functions: Mapping[Signature, LogicFunction] = dict(), +) -> Union[Library, Pluggable]: + if alias is None: + return Library.of(primitives, theory.clauses, operators, functions) + else: + return Library.of(alias, primitives, theory.clauses, operators, functions) + + +def aliased(alias: str, library: Library) -> Library: + return Library.of(alias, library) + + +def libraries( + *libs: Union[Library, Iterable[Library]], + **kwargs: Library +) -> Library: + all_libraries = [] + queue = list(libs) + while len(queue) > 0: + current = queue.pop() + if isinstance(current, Library): + all_libraries.append(current) + elif isinstance(current, Iterable): + queue.extend(current) + else: + raise TypeError(f'Expected Library or Iterable[Library], got {type(current)}') + for alias, library in kwargs.items(): + if isinstance(library, Library): + all_libraries.append(aliased(alias, kwargs[alias])) + return reduce(lambda a, b: a.plus(b), all_libraries, Library.of({}, [], operator_set(), {})) diff --git a/tuprolog/solve/library/_definititions.py b/tuprolog/solve/library/_definititions.py new file mode 100644 index 0000000..24e6a3e --- /dev/null +++ b/tuprolog/solve/library/_definititions.py @@ -0,0 +1,15 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.library as _library # type: ignore + + +Library = _library.Library + + +Pluggable = _library.Pluggable + + +Runtime = _library.Runtime + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.library.*") diff --git a/tuprolog/solve/library/exception/__init__.py b/tuprolog/solve/library/exception.py similarity index 99% rename from tuprolog/solve/library/exception/__init__.py rename to tuprolog/solve/library/exception.py index bbbe199..c202226 100644 --- a/tuprolog/solve/library/exception/__init__.py +++ b/tuprolog/solve/library/exception.py @@ -5,8 +5,10 @@ AlreadyLoadedLibraryException = _exception.AlreadyLoadedLibraryException + LibraryException = _exception.LibraryException + NoSuchALibraryException = _exception.NoSuchALibraryException diff --git a/tuprolog/solve/plp/__init__.py b/tuprolog/solve/plp/__init__.py index 0a23819..3272497 100644 --- a/tuprolog/solve/plp/__init__.py +++ b/tuprolog/solve/plp/__init__.py @@ -1,49 +1,2 @@ -from typing import TypeVar, Mapping, Any -from tuprolog import logger -from tuprolog.utils import Taggable -from tuprolog.solve import SolveOptions, solve_options as _solve_options, MAX_TIMEOUT, ALL_SOLUTIONS -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve as _solve # type: ignore - - -ProbExtensions = _solve.ProbExtensions - - -def probability(taggable: Taggable) -> float: - return ProbExtensions.getProbability(taggable) - - -T = TypeVar("T", bound=Taggable, covariant=True) - - -def set_probability(taggable: T) -> T: - return ProbExtensions.setProbability(taggable) - - -def is_probabilistic(solve_opts: SolveOptions) -> bool: - return ProbExtensions.isProbabilistic(solve_opts) - - -def set_probabilistic(solve_opts: SolveOptions, value: bool) -> SolveOptions: - return ProbExtensions.setProbabilistic(solve_opts, value) - - -def probabilistic(solve_opts: SolveOptions) -> SolveOptions: - return ProbExtensions.probabilistic(solve_opts) - - -def solve_options( - lazy: bool = True, - timeout: int = MAX_TIMEOUT, - limit: int = ALL_SOLUTIONS, - probabilistic: bool = False, - custom: Mapping[str, Any] = dict(), - **kwargs: Any -) -> SolveOptions: - non_probabilistic = _solve_options(lazy, timeout, limit, custom, **kwargs) - if probabilistic: - return set_probabilistic(non_probabilistic, True) - return non_probabilistic - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.plp.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/plp/_api.py b/tuprolog/solve/plp/_api.py new file mode 100644 index 0000000..6f24267 --- /dev/null +++ b/tuprolog/solve/plp/_api.py @@ -0,0 +1,41 @@ +from typing import TypeVar, Mapping, Any +from tuprolog.utils import Taggable +from tuprolog.solve import SolveOptions, solve_options as _solve_options, MAX_TIMEOUT, ALL_SOLUTIONS +from ._definitions import ProbExtensions + + +def probability(taggable: Taggable) -> float: + return ProbExtensions.getProbability(taggable) + + +T = TypeVar("T", bound=Taggable, covariant=True) + + +def set_probability(taggable: T) -> T: + return ProbExtensions.setProbability(taggable) + + +def is_probabilistic(solve_opts: SolveOptions) -> bool: + return ProbExtensions.isProbabilistic(solve_opts) + + +def set_probabilistic(solve_opts: SolveOptions, value: bool) -> SolveOptions: + return ProbExtensions.setProbabilistic(solve_opts, value) + + +def probabilistic(solve_opts: SolveOptions) -> SolveOptions: + return ProbExtensions.probabilistic(solve_opts) + + +def solve_options( + lazy: bool = True, + timeout: int = MAX_TIMEOUT, + limit: int = ALL_SOLUTIONS, + probabilistic: bool = False, + custom: Mapping[str, Any] = dict(), + **kwargs: Any +) -> SolveOptions: + non_probabilistic = _solve_options(lazy, timeout, limit, custom, **kwargs) + if probabilistic: + return set_probabilistic(non_probabilistic, True) + return non_probabilistic diff --git a/tuprolog/solve/plp/_definitions.py b/tuprolog/solve/plp/_definitions.py new file mode 100644 index 0000000..de4ea70 --- /dev/null +++ b/tuprolog/solve/plp/_definitions.py @@ -0,0 +1,9 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve as _solve # type: ignore + + +ProbExtensions = _solve.ProbExtensions + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.plp.*") diff --git a/tuprolog/solve/primitive/__init__.py b/tuprolog/solve/primitive/__init__.py index b4439a4..3272497 100644 --- a/tuprolog/solve/primitive/__init__.py +++ b/tuprolog/solve/primitive/__init__.py @@ -1,159 +1,2 @@ -from typing import List, Iterable, Callable -from tuprolog import logger -from tuprolog.core import Term, Clause, Integer -from tuprolog.solve import ExecutionContext, Signature, Solution, current_time_instant, MAX_TIMEOUT -from tuprolog.pyutils import iterable_or_varargs -from tuprolog.jvmutils import jlist -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.primitive as _primitive # type: ignore - - -Primitive = _primitive.Primitive - -Solve = _primitive.Solve - -PrimitiveWrapper = _primitive.PrimitiveWrapper - -SolveRequest = Solve.Request - -SolveResponse = Solve.Request - - -@jpype.JImplements(Primitive) -class AbstractPrimitive(object): - @jpype.JOverride - def solve(self, request: SolveRequest) -> Iterable[SolveResponse]: - raise NotImplementedError() - - -def primitive(callable: Callable[[SolveResponse], Iterable[SolveResponse]]) -> Primitive: - class CallableToPrimitiveAdapter(AbstractPrimitive): - def solve(self, request: SolveRequest) -> Iterable[SolveResponse]: - return callable(request) - - return CallableToPrimitiveAdapter() - - -def solve_request( - signature: Signature, - arguments: List[Term], - context: ExecutionContext, - issuing_instant: int = current_time_instant(), - max_duration: int = MAX_TIMEOUT -) -> SolveRequest: - return SolveRequest(signature, arguments, context, issuing_instant, max_duration) - - -def solve_response(solution: Solution, *side_effects) -> SolveResponse: - return iterable_or_varargs(side_effects, lambda ses: SolveResponse(solution, None, jlist(ses))) - - -def check_term_is_recursively_callable(request: SolveRequest, term: Term): - return PrimitiveWrapper.checkTermIsRecursivelyCallable(request, term) - - -def ensuring_all_arguments_are_instantiated(request: SolveRequest) -> SolveRequest: - return PrimitiveWrapper.ensuringAllArgumentsAreInstantiated(request) - - -def ensuring_procedure_has_permission(request: SolveRequest, signature: Signature, operation) -> SolveRequest: - return PrimitiveWrapper.ensuringProcedureHasPermission(request, signature, operation) - - -def ensuring_clause_procedure_has_permission(request: SolveRequest, clause: Clause, operation) -> SolveRequest: - return PrimitiveWrapper.ensuringClauseProcedureHasPermission(request, clause, operation) - - -def ensuring_argument_is_well_formed_indicator(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsWellFormedIndicator(request, index) - - -def not_implemented(request: SolveRequest, message: str) -> SolveResponse: - return PrimitiveWrapper.notImplemented(request, message) - - -def not_supported(request: SolveRequest, message: str) -> SolveResponse: - return PrimitiveWrapper.notSupported(request, message) - - -def ensuring_argument_is_well_formed_clause(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsWellFormedClause(request, index) - - -def ensuring_argument_is_instantiated(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsInstantiated(request, index) - - -def ensuring_argument_is_numeric(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsNumeric(request, index) - - -def ensuring_argument_is_struct(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsStruct(request, index) - - -def ensuring_argument_is_callable(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsCallable(request, index) - - -def ensuring_argument_is_variable(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsVariable(request, index) - - -def ensuring_argument_is_compound(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsCompound(request, index) - - -def ensuring_argument_is_atom(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsCompound(request, index) - - -def ensuring_argument_is_constant(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsConstant(request, index) - - -def ensuring_argument_is_ground(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsGround(request, index) - - -def ensuring_argument_is_char(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsChar(request, index) - - -def ensuring_argument_is_specifier(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsSpecifier(request, index) - - -def ensuring_argument_is_integer(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsInteger(request, index) - - -def ensuring_argument_is_list(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsList(request, index) - - -def ensuring_argument_is_arity(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsArity(request, index) - - -def ensuring_argument_is_non_negative_integer(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsNonNegativeInteger(request, index) - - -def is_character_code(integer: Integer) -> bool: - return PrimitiveWrapper.isCharacterCode(integer) - - -def ensuring_term_is_char_code(request: SolveRequest, term: Term) -> SolveRequest: - return PrimitiveWrapper.ensuringTermIsCharCode(request, term) - - -def ensuring_term_is_well_formed_list(request: SolveRequest, term: Term) -> SolveRequest: - return PrimitiveWrapper.ensuringTermIsWellFormedList(request, term) - - -def ensuring_argument_is_char_code(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsCharCode(request, index) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.primitive.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/primitive/_api.py b/tuprolog/solve/primitive/_api.py new file mode 100644 index 0000000..9421dfe --- /dev/null +++ b/tuprolog/solve/primitive/_api.py @@ -0,0 +1,136 @@ +from typing import List, Iterable, Callable +from tuprolog.pyutils import iterable_or_varargs +from tuprolog.jvmutils import jlist +from tuprolog.core import Term, Clause, Integer +from tuprolog.solve import ExecutionContext, Signature, Solution, current_time_instant, MAX_TIMEOUT +from ._definitions import Primitive, PrimitiveWrapper, SolveRequest, SolveResponse, AbstractPrimitive + + +def primitive(callable: Callable[[SolveResponse], Iterable[SolveResponse]]) -> Primitive: + class CallableToPrimitiveAdapter(AbstractPrimitive): + def solve(self, request: SolveRequest) -> Iterable[SolveResponse]: + return callable(request) + + return CallableToPrimitiveAdapter() + + +def solve_request( + signature: Signature, + arguments: List[Term], + context: ExecutionContext, + issuing_instant: int = current_time_instant(), + max_duration: int = MAX_TIMEOUT +) -> SolveRequest: + return SolveRequest(signature, arguments, context, issuing_instant, max_duration) + + +def solve_response(solution: Solution, *side_effects) -> SolveResponse: + return iterable_or_varargs(side_effects, lambda ses: SolveResponse(solution, None, jlist(ses))) + + +def check_term_is_recursively_callable(request: SolveRequest, term: Term): + return PrimitiveWrapper.checkTermIsRecursivelyCallable(request, term) + + +def ensuring_all_arguments_are_instantiated(request: SolveRequest) -> SolveRequest: + return PrimitiveWrapper.ensuringAllArgumentsAreInstantiated(request) + + +def ensuring_procedure_has_permission(request: SolveRequest, signature: Signature, operation) -> SolveRequest: + return PrimitiveWrapper.ensuringProcedureHasPermission(request, signature, operation) + + +def ensuring_clause_procedure_has_permission(request: SolveRequest, clause: Clause, operation) -> SolveRequest: + return PrimitiveWrapper.ensuringClauseProcedureHasPermission(request, clause, operation) + + +def ensuring_argument_is_well_formed_indicator(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsWellFormedIndicator(request, index) + + +def not_implemented(request: SolveRequest, message: str) -> SolveResponse: + return PrimitiveWrapper.notImplemented(request, message) + + +def not_supported(request: SolveRequest, message: str) -> SolveResponse: + return PrimitiveWrapper.notSupported(request, message) + + +def ensuring_argument_is_well_formed_clause(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsWellFormedClause(request, index) + + +def ensuring_argument_is_instantiated(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsInstantiated(request, index) + + +def ensuring_argument_is_numeric(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsNumeric(request, index) + + +def ensuring_argument_is_struct(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsStruct(request, index) + + +def ensuring_argument_is_callable(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsCallable(request, index) + + +def ensuring_argument_is_variable(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsVariable(request, index) + + +def ensuring_argument_is_compound(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsCompound(request, index) + + +def ensuring_argument_is_atom(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsCompound(request, index) + + +def ensuring_argument_is_constant(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsConstant(request, index) + + +def ensuring_argument_is_ground(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsGround(request, index) + + +def ensuring_argument_is_char(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsChar(request, index) + + +def ensuring_argument_is_specifier(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsSpecifier(request, index) + + +def ensuring_argument_is_integer(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsInteger(request, index) + + +def ensuring_argument_is_list(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsList(request, index) + + +def ensuring_argument_is_arity(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsArity(request, index) + + +def ensuring_argument_is_non_negative_integer(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsNonNegativeInteger(request, index) + + +def is_character_code(integer: Integer) -> bool: + return PrimitiveWrapper.isCharacterCode(integer) + + +def ensuring_term_is_char_code(request: SolveRequest, term: Term) -> SolveRequest: + return PrimitiveWrapper.ensuringTermIsCharCode(request, term) + + +def ensuring_term_is_well_formed_list(request: SolveRequest, term: Term) -> SolveRequest: + return PrimitiveWrapper.ensuringTermIsWellFormedList(request, term) + + +def ensuring_argument_is_char_code(request: SolveRequest, index: int) -> SolveRequest: + return PrimitiveWrapper.ensuringArgumentIsCharCode(request, index) diff --git a/tuprolog/solve/primitive/_definitions.py b/tuprolog/solve/primitive/_definitions.py new file mode 100644 index 0000000..02c5b0b --- /dev/null +++ b/tuprolog/solve/primitive/_definitions.py @@ -0,0 +1,30 @@ +from typing import Iterable +from jpype import JImplements, JOverride +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.primitive as _primitive # type: ignore + + +Primitive = _primitive.Primitive + + +Solve = _primitive.Solve + + +PrimitiveWrapper = _primitive.PrimitiveWrapper + + +SolveRequest = Solve.Request + + +SolveResponse = Solve.Response + + +@JImplements(Primitive) +class AbstractPrimitive(object): + @JOverride + def solve(self, request: SolveRequest) -> Iterable[SolveResponse]: + raise NotImplementedError() + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.primitive.*") diff --git a/tuprolog/solve/sideffcts/__init__.py b/tuprolog/solve/sideffcts/__init__.py deleted file mode 100644 index 74b7304..0000000 --- a/tuprolog/solve/sideffcts/__init__.py +++ /dev/null @@ -1,167 +0,0 @@ -from typing import Mapping, Union, Iterable, Any -from tuprolog import logger -from tuprolog.core import Clause, Term -from tuprolog.pyutils import iterable_or_varargs, dict_or_keyword_args -from tuprolog.jvmutils import jlist, jmap -from tuprolog.core.operators import Operator, OperatorSet -from tuprolog.solve.library import Library, libraries as new_libraries -from tuprolog.solve.channel import InputChannel, OutputChannel -import jpype.imports # noqa: F401 -from it.unibo.tuprolog.solve.sideffects import SideEffect # type: ignore - - -def _forward_iterable_or_varargs(callable, args, *callable_args): - return iterable_or_varargs(args, lambda xs: callable(jlist(xs), *callable_args)) - - -def _forward_dict_or_keywords(callable, dict, kwargs, *callable_args): - return dict_or_keyword_args(dict, kwargs, lambda ds: callable(jmap(ds), *callable_args)) - - -def reset_static_kb(*clauses: Union[Clause, Iterable[Clause]]) -> SideEffect.ResetStaticKb: - return _forward_iterable_or_varargs(SideEffect.ResetStaticKb, clauses) - - -def add_static_clauses(*clauses: Union[Clause, Iterable[Clause]]) -> SideEffect.AddStaticClauses: - return _forward_iterable_or_varargs(SideEffect.AddStaticClauses, clauses) - - -def remove_static_clauses(*clauses: Union[Clause, Iterable[Clause]]) -> SideEffect.RemoveStaticClauses: - return _forward_iterable_or_varargs(SideEffect.RemoveStaticClauses, clauses) - - -def reset_dynamic_kb(*clauses: Union[Clause, Iterable[Clause]]) -> SideEffect.ResetDynamicKb: - return _forward_iterable_or_varargs(SideEffect.ResetDynamicKb, clauses) - - -def add_dynamic_clauses(*clauses: Union[Clause, Iterable[Clause]]) -> SideEffect.AddDynamicClauses: - return _forward_iterable_or_varargs(SideEffect.AddDynamicClauses, clauses) - - -def remove_dynamic_clauses(*clauses: Union[Clause, Iterable[Clause]]) -> SideEffect.RemoveDynamicClauses: - return _forward_iterable_or_varargs(SideEffect.RemoveDynamicClauses, clauses) - - -def set_flags(flags: Mapping[str, Term] = {}, **kwargs: Term) -> SideEffect.SetFlags: - return _forward_dict_or_keywords(SideEffect.SetFlags, flags, kwargs) - - -def reset_flags(flags: Mapping[str, Term] = {}, **kwargs: Term) -> SideEffect.ResetFlags: - return _forward_dict_or_keywords(SideEffect.ResetFlags, flags, kwargs) - - -def clear_flags(*flag_names: str) -> SideEffect.ClearFlags: - return _forward_iterable_or_varargs(SideEffect.ClearFlags, flag_names) - - -def load_library(alias: str, library: Library) -> SideEffect.LoadLibrary: - return SideEffect.LoadLibrary(alias, library) - - -def unload_libraries(*aliases: str) -> SideEffect.UnloadLibraries: - return _forward_iterable_or_varargs(SideEffect.UnloadLibraries, aliases) - - -def update_library(alias: str, library: Library) -> SideEffect.UpdateLibrary: - return SideEffect.UpdateLibrary(alias, library) - - -def add_libraries(*libraries: Library) -> SideEffect.AddLibraries: - return SideEffect.AddLibraries(new_libraries(libraries)) - - -def reset_libraries(*libraries: Library) -> SideEffect.ResetRuntime: - return SideEffect.ResetRuntime(new_libraries(libraries)) - - -def set_operators(*operators: Union[Operator, Iterable[Operator]]) -> SideEffect.SetOperators: - return _forward_iterable_or_varargs(SideEffect.SetOperators, operators) - - -def reset_operators(*operators: Union[Operator, Iterable[Operator]]) -> SideEffect.ResetOperators: - return _forward_iterable_or_varargs(SideEffect.ResetOperators, operators) - - -def remove_operators(*operators: Union[Operator, Iterable[Operator]]) -> SideEffect.RemoveOperators: - return _forward_iterable_or_varargs(SideEffect.RemoveOperators, operators) - - -def open_input_channels( - channels: Mapping[str, InputChannel] = {}, - **kwargs: InputChannel -) -> SideEffect.OpenInputChannels: - return _forward_dict_or_keywords(SideEffect.OpenInputChannels, channels, kwargs) - - -def reset_input_channels( - channels: Mapping[str, InputChannel] = {}, - **kwargs: InputChannel -) -> SideEffect.ResetInputChannels: - return _forward_dict_or_keywords(SideEffect.ResetInputChannels, channels, kwargs) - - -def close_input_channels(*names: Union[str, Iterable[str]]) -> SideEffect.CloseInputChannels: - return _forward_iterable_or_varargs(SideEffect.CloseInputChannels, names) - - -def open_output_channels( - channels: Mapping[str, OutputChannel] = {}, - **kwargs: OutputChannel -) -> SideEffect.OpenOutputChannels: - return _forward_dict_or_keywords(SideEffect.OpenOutputChannels, channels, kwargs) - - -def reset_output_channels( - channels: Mapping[str, OutputChannel] = {}, - **kwargs: OutputChannel -) -> SideEffect.ResetOutputChannels: - return _forward_dict_or_keywords(SideEffect.ResetOutputChannels, channels, kwargs) - - -def close_output_channels(*names: Union[str, Iterable[str]]) -> SideEffect.CloseOutputChannels: - return _forward_iterable_or_varargs(SideEffect.CloseOutputChannels, names) - - -def set_persistent_data( - data: Mapping[str, Any] = {}, - **kwargs: Any -) -> SideEffect.SetPersistentData: - return _forward_dict_or_keywords(SideEffect.SetPersistentData, data, kwargs, False) - - -def reset_persistent_data( - data: Mapping[str, Any] = {}, - **kwargs: Any -) -> SideEffect.SetPersistentData: - return _forward_dict_or_keywords(SideEffect.SetPersistentData, data, kwargs, True) - - -def set_durable_data( - data: Mapping[str, Any] = {}, - **kwargs: Any -) -> SideEffect.SetDurableData: - return _forward_dict_or_keywords(SideEffect.SetDurableData, data, kwargs, False) - - -def reset_durable_data( - data: Mapping[str, Any] = {}, - **kwargs: Any -) -> SideEffect.SetDurableData: - return _forward_dict_or_keywords(SideEffect.SetDurableData, data, kwargs, True) - - -def set_ephemeral_data( - data: Mapping[str, Any] = {}, - **kwargs: Any -) -> SideEffect.SetEphemeralData: - return _forward_dict_or_keywords(SideEffect.SetEphemeralData, data, kwargs, False) - - -def reset_ephemeral_data( - data: Mapping[str, Any] = {}, - **kwargs: Any -) -> SideEffect.SetEphemeralData: - return _forward_dict_or_keywords(SideEffect.SetEphemeralData, data, kwargs, True) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.sideffects.*") diff --git a/tuprolog/solve/sideffects/__init__.py b/tuprolog/solve/sideffects/__init__.py new file mode 100644 index 0000000..3272497 --- /dev/null +++ b/tuprolog/solve/sideffects/__init__.py @@ -0,0 +1,2 @@ +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/sideffects/_api.py b/tuprolog/solve/sideffects/_api.py new file mode 100644 index 0000000..60ac411 --- /dev/null +++ b/tuprolog/solve/sideffects/_api.py @@ -0,0 +1,166 @@ +from typing import Mapping, Union, Iterable, Any +from tuprolog.core import Clause, Term +from tuprolog.pyutils import iterable_or_varargs, dict_or_keyword_args +from tuprolog.jvmutils import jlist, jmap +from tuprolog.core.operators import Operator +from tuprolog.solve.library import Library, libraries as new_libraries +from tuprolog.solve.channel import InputChannel, OutputChannel +from ._definitions import ResetStaticKb, AddStaticClauses, RemoveStaticClauses, ResetDynamicKb, AddDynamicClauses, \ + RemoveDynamicClauses, SetFlags, ResetFlags, ClearFlags, LoadLibrary, UnloadLibraries, UpdateLibrary, AddLibraries, \ + ResetRuntime, SetOperators, ResetOperators, RemoveOperators, OpenInputChannels, ResetInputChannels, \ + CloseInputChannels, OpenOutputChannels, ResetOutputChannels, CloseOutputChannels, SetPersistentData, SetDurableData, \ + SetEphemeralData + + +def _forward_iterable_or_varargs(callable, args, *callable_args): + return iterable_or_varargs(args, lambda xs: callable(jlist(xs), *callable_args)) + + +def _forward_dict_or_keywords(callable, dict, kwargs, *callable_args): + return dict_or_keyword_args(dict, kwargs, lambda ds: callable(jmap(ds), *callable_args)) + + +def reset_static_kb(*clauses: Union[Clause, Iterable[Clause]]) -> ResetStaticKb: + return _forward_iterable_or_varargs(ResetStaticKb, clauses) + + +def add_static_clauses(*clauses: Union[Clause, Iterable[Clause]]) -> AddStaticClauses: + return _forward_iterable_or_varargs(AddStaticClauses, clauses) + + +def remove_static_clauses(*clauses: Union[Clause, Iterable[Clause]]) -> RemoveStaticClauses: + return _forward_iterable_or_varargs(RemoveStaticClauses, clauses) + + +def reset_dynamic_kb(*clauses: Union[Clause, Iterable[Clause]]) -> ResetDynamicKb: + return _forward_iterable_or_varargs(ResetDynamicKb, clauses) + + +def add_dynamic_clauses(*clauses: Union[Clause, Iterable[Clause]]) -> AddDynamicClauses: + return _forward_iterable_or_varargs(AddDynamicClauses, clauses) + + +def remove_dynamic_clauses(*clauses: Union[Clause, Iterable[Clause]]) -> RemoveDynamicClauses: + return _forward_iterable_or_varargs(RemoveDynamicClauses, clauses) + + +def set_flags(flags: Mapping[str, Term] = {}, **kwargs: Term) -> SetFlags: + return _forward_dict_or_keywords(SetFlags, flags, kwargs) + + +def reset_flags(flags: Mapping[str, Term] = {}, **kwargs: Term) -> ResetFlags: + return _forward_dict_or_keywords(ResetFlags, flags, kwargs) + + +def clear_flags(*flag_names: str) -> ClearFlags: + return _forward_iterable_or_varargs(ClearFlags, flag_names) + + +def load_library(alias: str, library: Library) -> LoadLibrary: + return LoadLibrary(alias, library) + + +def unload_libraries(*aliases: str) -> UnloadLibraries: + return _forward_iterable_or_varargs(UnloadLibraries, aliases) + + +def update_library(alias: str, library: Library) -> UpdateLibrary: + return UpdateLibrary(alias, library) + + +def add_libraries(*libraries: Library) -> AddLibraries: + return AddLibraries(new_libraries(libraries)) + + +def reset_libraries(*libraries: Library) -> ResetRuntime: + return ResetRuntime(new_libraries(libraries)) + + +def set_operators(*operators: Union[Operator, Iterable[Operator]]) -> SetOperators: + return _forward_iterable_or_varargs(SetOperators, operators) + + +def reset_operators(*operators: Union[Operator, Iterable[Operator]]) -> ResetOperators: + return _forward_iterable_or_varargs(ResetOperators, operators) + + +def remove_operators(*operators: Union[Operator, Iterable[Operator]]) -> RemoveOperators: + return _forward_iterable_or_varargs(RemoveOperators, operators) + + +def open_input_channels( + channels: Mapping[str, InputChannel] = {}, + **kwargs: InputChannel +) -> OpenInputChannels: + return _forward_dict_or_keywords(OpenInputChannels, channels, kwargs) + + +def reset_input_channels( + channels: Mapping[str, InputChannel] = {}, + **kwargs: InputChannel +) -> ResetInputChannels: + return _forward_dict_or_keywords(ResetInputChannels, channels, kwargs) + + +def close_input_channels(*names: Union[str, Iterable[str]]) -> CloseInputChannels: + return _forward_iterable_or_varargs(CloseInputChannels, names) + + +def open_output_channels( + channels: Mapping[str, OutputChannel] = {}, + **kwargs: OutputChannel +) -> OpenOutputChannels: + return _forward_dict_or_keywords(OpenOutputChannels, channels, kwargs) + + +def reset_output_channels( + channels: Mapping[str, OutputChannel] = {}, + **kwargs: OutputChannel +) -> ResetOutputChannels: + return _forward_dict_or_keywords(ResetOutputChannels, channels, kwargs) + + +def close_output_channels(*names: Union[str, Iterable[str]]) -> CloseOutputChannels: + return _forward_iterable_or_varargs(CloseOutputChannels, names) + + +def set_persistent_data( + data: Mapping[str, Any] = {}, + **kwargs: Any +) -> SetPersistentData: + return _forward_dict_or_keywords(SetPersistentData, data, kwargs, False) + + +def reset_persistent_data( + data: Mapping[str, Any] = {}, + **kwargs: Any +) -> SetPersistentData: + return _forward_dict_or_keywords(SetPersistentData, data, kwargs, True) + + +def set_durable_data( + data: Mapping[str, Any] = {}, + **kwargs: Any +) -> SetDurableData: + return _forward_dict_or_keywords(SetDurableData, data, kwargs, False) + + +def reset_durable_data( + data: Mapping[str, Any] = {}, + **kwargs: Any +) -> SetDurableData: + return _forward_dict_or_keywords(SetDurableData, data, kwargs, True) + + +def set_ephemeral_data( + data: Mapping[str, Any] = {}, + **kwargs: Any +) -> SetEphemeralData: + return _forward_dict_or_keywords(SetEphemeralData, data, kwargs, False) + + +def reset_ephemeral_data( + data: Mapping[str, Any] = {}, + **kwargs: Any +) -> SetEphemeralData: + return _forward_dict_or_keywords(SetEphemeralData, data, kwargs, True) diff --git a/tuprolog/solve/sideffects/_definitions.py b/tuprolog/solve/sideffects/_definitions.py new file mode 100644 index 0000000..cfde09c --- /dev/null +++ b/tuprolog/solve/sideffects/_definitions.py @@ -0,0 +1,99 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.sideffects as _sideffects # type: ignore + + +SideEffect = _sideffects.SideEffect + + +ResetStaticKb = SideEffect.ResetStaticKb + + +AddStaticClauses = SideEffect.AddStaticClauses + + +RemoveStaticClauses = SideEffect.RemoveStaticClauses + + +ResetDynamicKb = SideEffect.ResetDynamicKb + + +AddDynamicClauses = SideEffect.AddDynamicClauses + + +RemoveDynamicClauses = SideEffect.RemoveDynamicClauses + + +SetFlags = SideEffect.SetFlags + + +ResetFlags = SideEffect.ResetFlags + + +ClearFlags = SideEffect.ClearFlags + + +LoadLibrary = SideEffect.LoadLibrary + + +UnloadLibraries = SideEffect.UnloadLibraries + + +UpdateLibrary = SideEffect.UpdateLibrary + + +AddLibraries = SideEffect.AddLibraries + + +ResetRuntime = SideEffect.ResetRuntime + + +SetOperators = SideEffect.SetOperators + + +ResetOperators = SideEffect.ResetOperators + + +RemoveOperators = SideEffect.RemoveOperators + + +OpenInputChannels = SideEffect.OpenInputChannels + + +ResetInputChannels = SideEffect.ResetInputChannels + + +CloseInputChannels = SideEffect.CloseInputChannels + + +OpenOutputChannels = SideEffect.OpenOutputChannels + + +ResetOutputChannels = SideEffect.ResetOutputChannels + + +CloseOutputChannels = SideEffect.CloseOutputChannels + + +SetPersistentData = SideEffect.SetPersistentData + + +SetDurableData = SideEffect.SetDurableData + + +SetEphemeralData = SideEffect.SetEphemeralData + + +SideEffectFactory = _sideffects.SideEffectFactory + + +DEFAULT_SIDE_EFFECT_FACTORY = SideEffectFactory.getDefault() + + +SideEffectManager = _sideffects.SideEffectManager + + +SideEffectsBuilder = _sideffects.SideEffectsBuilder + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.sideffects.*") diff --git a/tuprolog/solve/stdlib/__init__.py b/tuprolog/solve/stdlib/__init__.py index 0bfdef5..47c7575 100644 --- a/tuprolog/solve/stdlib/__init__.py +++ b/tuprolog/solve/stdlib/__init__.py @@ -1,15 +1 @@ -from tuprolog import logger -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.stdlib as _stdlib # type: ignore - - -CommonBuiltins = _stdlib.CommonBuiltins - -CommonFunctions = _stdlib.CommonFunctions - -CommonPrimitives = _stdlib.CommonPrimitives - -CommonRules = _stdlib.CommonRules - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.stdlib.*") +from ._definitions import * diff --git a/tuprolog/solve/stdlib/_definitions.py b/tuprolog/solve/stdlib/_definitions.py new file mode 100644 index 0000000..2b0ac89 --- /dev/null +++ b/tuprolog/solve/stdlib/_definitions.py @@ -0,0 +1,18 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.stdlib as _stdlib # type: ignore + + +CommonBuiltins : _stdlib.CommonBuiltins = _stdlib.CommonBuiltins.INSTANCE + + +CommonFunctions : _stdlib.CommonFunctions = _stdlib.CommonFunctions.INSTANCE + + +CommonPrimitives : _stdlib.CommonPrimitives = _stdlib.CommonPrimitives.INSTANCE + + +CommonRules : _stdlib.CommonRules = _stdlib.CommonRules.INSTANCE + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.stdlib.*") diff --git a/tuprolog/solve/stdlib/function/__init__.py b/tuprolog/solve/stdlib/function.py similarity index 98% rename from tuprolog/solve/stdlib/function/__init__.py rename to tuprolog/solve/stdlib/function.py index 1f25ce7..968506b 100644 --- a/tuprolog/solve/stdlib/function/__init__.py +++ b/tuprolog/solve/stdlib/function.py @@ -5,60 +5,88 @@ AbsoluteValue = _function.AbsoluteValue.INSTANCE + Addition = _function.Addition.INSTANCE + ArcTangent = _function.ArcTangent.INSTANCE + BitwiseAnd = _function.BitwiseAnd.INSTANCE + BitwiseComplement = _function.BitwiseComplement.INSTANCE + BitwiseLeftShift = _function.BitwiseLeftShift.INSTANCE + BitwiseOr = _function.BitwiseOr.INSTANCE + BitwiseRightShift = _function.BitwiseRightShift.INSTANCE + Ceiling = _function.Ceiling.INSTANCE + Cosine = _function.Cosine.INSTANCE + Exponential = _function.Exponential.INSTANCE + Exponentiation = _function.Exponentiation.INSTANCE + FloatFractionalPart = _function.FloatFractionalPart.INSTANCE + FloatIntegerPart = _function.FloatIntegerPart.INSTANCE + FloatingPointDivision = _function.FloatingPointDivision.INSTANCE + Floor = _function.Floor.INSTANCE + IntegerDivision = _function.IntegerDivision.INSTANCE + Modulo = _function.Modulo.INSTANCE + Multiplication = _function.Multiplication.INSTANCE + NaturalLogarithm = _function.NaturalLogarithm.INSTANCE + Remainder = _function.Remainder.INSTANCE + Round = _function.Round.INSTANCE + Sign = _function.Sign.INSTANCE + SignReversal = _function.SignReversal.INSTANCE + Sine = _function.Sine.INSTANCE + SquareRoot = _function.SquareRoot.INSTANCE + Subtraction = _function.Subtraction.INSTANCE + ToFloat = _function.ToFloat.INSTANCE + Truncate = _function.Truncate.INSTANCE diff --git a/tuprolog/solve/stdlib/magic.py b/tuprolog/solve/stdlib/magic.py new file mode 100644 index 0000000..7f82376 --- /dev/null +++ b/tuprolog/solve/stdlib/magic.py @@ -0,0 +1,9 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.stdlib.magic as _magic # type: ignore + + +MagicCut : _magic.MagicCut = _magic.MagicCut.INSTANCE + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.stdlib.magic.*") diff --git a/tuprolog/solve/stdlib/primitive.py b/tuprolog/solve/stdlib/primitive.py new file mode 100644 index 0000000..6b249ac --- /dev/null +++ b/tuprolog/solve/stdlib/primitive.py @@ -0,0 +1,214 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.stdlib.primitive as _primitive # type: ignore + + +Abolish : _primitive.Abolish = _primitive.Abolish.INSTANCE + + +Arg : _primitive.Arg = _primitive.Arg.INSTANCE + + +ArithmeticEqual : _primitive.ArithmeticEqual = _primitive.ArithmeticEqual.INSTANCE + + +ArithmeticGreaterThan : _primitive.ArithmeticGreaterThan = _primitive.ArithmeticGreaterThan.INSTANCE + + +ArithmeticGreaterThanOrEqualTo : _primitive.ArithmeticGreaterThanOrEqualTo = _primitive.ArithmeticGreaterThanOrEqualTo.INSTANCE + + +ArithmeticLowerThan : _primitive.ArithmeticLowerThan = _primitive.ArithmeticLowerThan.INSTANCE + + +ArithmeticLowerThanOrEqualTo : _primitive.ArithmeticLowerThanOrEqualTo = _primitive.ArithmeticLowerThanOrEqualTo.INSTANCE + + +ArithmeticNotEqual : _primitive.ArithmeticNotEqual = _primitive.ArithmeticNotEqual.INSTANCE + + +Assert : _primitive.Assert = _primitive.Assert.INSTANCE + + +AssertA : _primitive.AssertA = _primitive.AssertA.INSTANCE + + +AssertZ : _primitive.AssertZ = _primitive.AssertZ.INSTANCE + + +Atom : _primitive.Atom = _primitive.Atom.INSTANCE + + +AtomChars : _primitive.AtomChars = _primitive.AtomChars.INSTANCE + + +AtomCodes : _primitive.AtomCodes = _primitive.AtomCodes.INSTANCE + + +AtomConcat : _primitive.AtomConcat = _primitive.AtomConcat.INSTANCE + + +AtomLength : _primitive.AtomLength = _primitive.AtomLength.INSTANCE + + +Atomic : _primitive.Atomic = _primitive.Atomic.INSTANCE + + +BagOf : _primitive.BagOf = _primitive.BagOf.INSTANCE + + +Between : _primitive.Between = _primitive.Between.INSTANCE + + +Callable : _primitive.Callable = _primitive.Callable.INSTANCE + + +CharCode : _primitive.CharCode = _primitive.CharCode.INSTANCE + + +Clause : _primitive.Clause = _primitive.Clause.INSTANCE + + +Compound : _primitive.Compound = _primitive.Compound.INSTANCE + + +CopyTerm : _primitive.CopyTerm = _primitive.CopyTerm.INSTANCE + + +CurrentFlag : _primitive.CurrentFlag = _primitive.CurrentFlag.INSTANCE + + +CurrentOp : _primitive.CurrentOp = _primitive.CurrentOp.INSTANCE + + +EnsureExecutable : _primitive.EnsureExecutable = _primitive.EnsureExecutable.INSTANCE + + +FindAll : _primitive.FindAll = _primitive.FindAll.INSTANCE + + +Float : _primitive.Float = _primitive.Float.INSTANCE + + +Functor : _primitive.Functor = _primitive.Functor.INSTANCE + + +GetDurable : _primitive.GetDurable = _primitive.GetDurable.INSTANCE + + +GetEphemeral : _primitive.GetEphemeral = _primitive.GetEphemeral.INSTANCE + + +GetPersistent : _primitive.GetPersistent = _primitive.GetPersistent.INSTANCE + + +Ground : _primitive.Ground = _primitive.Ground.INSTANCE + + +Halt : _primitive.Halt = _primitive.Halt.INSTANCE + + +Halt1 : _primitive.Halt1 = _primitive.Halt1.INSTANCE + + +Integer : _primitive.Integer = _primitive.Integer.INSTANCE + + +Is : _primitive.Is = _primitive.Is.INSTANCE + + +Natural : _primitive.Natural = _primitive.Natural.INSTANCE + + +NewLine : _primitive.NewLine = _primitive.NewLine.INSTANCE + + +NonVar : _primitive.NonVar = _primitive.NonVar.INSTANCE + + +NotUnifiableWith : _primitive.NotUnifiableWith = _primitive.NotUnifiableWith.INSTANCE + + +Number : _primitive.Number = _primitive.Number.INSTANCE + + +NumberChars : _primitive.NumberChars = _primitive.NumberChars.INSTANCE + + +NumberCodes : _primitive.NumberCodes = _primitive.NumberCodes.INSTANCE + + +Op : _primitive.Op = _primitive.Op.INSTANCE + + +Repeat : _primitive.Repeat = _primitive.Repeat.INSTANCE + + +Retract : _primitive.Retract = _primitive.Retract.INSTANCE + + +RetractAll : _primitive.RetractAll = _primitive.RetractAll.INSTANCE + + +Reverse : _primitive.Reverse = _primitive.Reverse.INSTANCE + + +SetDurable : _primitive.SetDurable = _primitive.SetDurable.INSTANCE + + +SetEphemeral : _primitive.SetEphemeral = _primitive.SetEphemeral.INSTANCE + + +SetFlag : _primitive.SetFlag = _primitive.SetFlag.INSTANCE + + +SetOf : _primitive.SetOf = _primitive.SetOf.INSTANCE + + +SetPersistent : _primitive.SetPersistent = _primitive.SetPersistent.INSTANCE + + +Sleep : _primitive.Sleep = _primitive.Sleep.INSTANCE + + +SubAtom : _primitive.SubAtom = _primitive.SubAtom.INSTANCE + + +TermGreaterThan : _primitive.TermGreaterThan = _primitive.TermGreaterThan.INSTANCE + + +TermGreaterThanOrEqualTo : _primitive.TermGreaterThanOrEqualTo = _primitive.TermGreaterThanOrEqualTo.INSTANCE + + +TermIdentical : _primitive.TermIdentical = _primitive.TermIdentical.INSTANCE + + +TermLowerThan : _primitive.TermLowerThan = _primitive.TermLowerThan.INSTANCE + + +TermLowerThanOrEqualTo : _primitive.TermLowerThanOrEqualTo = _primitive.TermLowerThanOrEqualTo.INSTANCE + + +TermNotIdentical : _primitive.TermNotIdentical = _primitive.TermNotIdentical.INSTANCE + + +TermNotSame : _primitive.TermNotSame = _primitive.TermNotSame.INSTANCE + + +TermSame : _primitive.TermSame = _primitive.TermSame.INSTANCE + + +UnifiesWith : _primitive.UnifiesWith = _primitive.UnifiesWith.INSTANCE + + +Univ : _primitive.Univ = _primitive.Univ.INSTANCE + + +Var : _primitive.Var = _primitive.Var.INSTANCE + + +Write : _primitive.Write = _primitive.Write.INSTANCE + + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.stdlib.primitive.*") diff --git a/tuprolog/solve/stdlib/primitive/__init__.py b/tuprolog/solve/stdlib/primitive/__init__.py deleted file mode 100644 index 45d84cd..0000000 --- a/tuprolog/solve/stdlib/primitive/__init__.py +++ /dev/null @@ -1,145 +0,0 @@ -from tuprolog import logger -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.stdlib.primitive as _primitive # type: ignore - - -Abolish = _primitive.Abolish.INSTANCE - -Arg = _primitive.Arg.INSTANCE - -ArithmeticEqual = _primitive.ArithmeticEqual.INSTANCE - -ArithmeticGreaterThan = _primitive.ArithmeticGreaterThan.INSTANCE - -ArithmeticGreaterThanOrEqualTo = _primitive.ArithmeticGreaterThanOrEqualTo.INSTANCE - -ArithmeticLowerThan = _primitive.ArithmeticLowerThan.INSTANCE - -ArithmeticLowerThanOrEqualTo = _primitive.ArithmeticLowerThanOrEqualTo.INSTANCE - -ArithmeticNotEqual = _primitive.ArithmeticNotEqual.INSTANCE - -Assert = _primitive.Assert.INSTANCE - -AssertA = _primitive.AssertA.INSTANCE - -AssertZ = _primitive.AssertZ.INSTANCE - -Atom = _primitive.Atom.INSTANCE - -AtomChars = _primitive.AtomChars.INSTANCE - -AtomCodes = _primitive.AtomCodes.INSTANCE - -AtomConcat = _primitive.AtomConcat.INSTANCE - -AtomLength = _primitive.AtomLength.INSTANCE - -Atomic = _primitive.Atomic.INSTANCE - -BagOf = _primitive.BagOf.INSTANCE - -Between = _primitive.Between.INSTANCE - -Callable = _primitive.Callable.INSTANCE - -CharCode = _primitive.CharCode.INSTANCE - -Clause = _primitive.Clause.INSTANCE - -Compound = _primitive.Compound.INSTANCE - -CopyTerm = _primitive.CopyTerm.INSTANCE - -CurrentFlag = _primitive.CurrentFlag.INSTANCE - -CurrentOp = _primitive.CurrentOp.INSTANCE - -EnsureExecutable = _primitive.EnsureExecutable.INSTANCE - -FindAll = _primitive.FindAll.INSTANCE - -Float = _primitive.Float.INSTANCE - -Functor = _primitive.Functor.INSTANCE - -GetDurable = _primitive.GetDurable.INSTANCE - -GetEphemeral = _primitive.GetEphemeral.INSTANCE - -GetPersistent = _primitive.GetPersistent.INSTANCE - -Ground = _primitive.Ground.INSTANCE - -Halt = _primitive.Halt.INSTANCE - -Halt1 = _primitive.Halt1.INSTANCE - -Integer = _primitive.Integer.INSTANCE - -Is = _primitive.Is.INSTANCE - -Natural = _primitive.Natural.INSTANCE - -NewLine = _primitive.NewLine.INSTANCE - -NonVar = _primitive.NonVar.INSTANCE - -NotUnifiableWith = _primitive.NotUnifiableWith.INSTANCE - -Number = _primitive.Number.INSTANCE - -NumberChars = _primitive.NumberChars.INSTANCE - -NumberCodes = _primitive.NumberCodes.INSTANCE - -Op = _primitive.Op.INSTANCE - -Repeat = _primitive.Repeat.INSTANCE - -Retract = _primitive.Retract.INSTANCE - -RetractAll = _primitive.RetractAll.INSTANCE - -Reverse = _primitive.Reverse.INSTANCE - -SetDurable = _primitive.SetDurable.INSTANCE - -SetEphemeral = _primitive.SetEphemeral.INSTANCE - -SetFlag = _primitive.SetFlag.INSTANCE - -SetOf = _primitive.SetOf.INSTANCE - -SetPersistent = _primitive.SetPersistent.INSTANCE - -Sleep = _primitive.Sleep.INSTANCE - -SubAtom = _primitive.SubAtom.INSTANCE - -TermGreaterThan = _primitive.TermGreaterThan.INSTANCE - -TermGreaterThanOrEqualTo = _primitive.TermGreaterThanOrEqualTo.INSTANCE - -TermIdentical = _primitive.TermIdentical.INSTANCE - -TermLowerThan = _primitive.TermLowerThan.INSTANCE - -TermLowerThanOrEqualTo = _primitive.TermLowerThanOrEqualTo.INSTANCE - -TermNotIdentical = _primitive.TermNotIdentical.INSTANCE - -TermNotSame = _primitive.TermNotSame.INSTANCE - -TermSame = _primitive.TermSame.INSTANCE - -UnifiesWith = _primitive.UnifiesWith.INSTANCE - -Univ = _primitive.Univ.INSTANCE - -Var = _primitive.Var.INSTANCE - -Write = _primitive.Write.INSTANCE - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.stdlib.primitive.*") diff --git a/tuprolog/solve/stdlib/rule.py b/tuprolog/solve/stdlib/rule.py new file mode 100644 index 0000000..4182f1c --- /dev/null +++ b/tuprolog/solve/stdlib/rule.py @@ -0,0 +1,73 @@ +from tuprolog import logger +from tuprolog.solve import signature +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.solve.stdlib.rule as _rule # type: ignore + + +_Append = _rule.Append + + +class Append: + FUNCTOR = _Append.FUNCTOR + + ARITY = _Append.ARITY + + SIGNATURE = signature(FUNCTOR, ARITY) + + Base = _Append.Base.INSTANCE + + Recursive = _Append.Recursive.INSTANCE + + +Arrow : _rule.Arrow = _rule.Arrow.INSTANCE + + +CurrentPrologFlag : _rule.CurrentPrologFlag = _rule.CurrentPrologFlag.INSTANCE + + +_Member = _rule.Member + + +class Member: + FUNCTOR = _Member.FUNCTOR + + ARITY = _Member.ARITY + + SIGNATURE = signature(FUNCTOR, ARITY) + + Base = _Member.Base.INSTANCE + + Recursive = _Member.Recursive.INSTANCE + + +Not : _rule.Not = _rule.Not.INSTANCE + + +Once : _rule.Once = _rule.Once.INSTANCE + + +_Semicolon = _rule.Semicolon + + +class Semicolon: + FUNCTOR = _Semicolon.FUNCTOR + + ARITY = _Semicolon.ARITY + + SIGNATURE = signature(FUNCTOR, ARITY) + + class If: + Then = _Semicolon.If.Then.INSTANCE + + Else = _Semicolon.If.Else.INSTANCE + + class Or: + Left = _Semicolon.Or.Left.INSTANCE + + Right = _Semicolon.Or.Right.INSTANCE + + +SetPrologFlag : _rule.SetPrologFlag = _rule.SetPrologFlag.INSTANCE + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.stdlib.rule.*") diff --git a/tuprolog/solve/stdlib/rule/__init__.py b/tuprolog/solve/stdlib/rule/__init__.py deleted file mode 100644 index a3d9250..0000000 --- a/tuprolog/solve/stdlib/rule/__init__.py +++ /dev/null @@ -1,76 +0,0 @@ -from tuprolog import logger -from tuprolog.solve import signature -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.solve.stdlib.rule as _rule # type: ignore - - -KtAppend = _rule.Append - -Arrow = _rule.Arrow - -CurrentPrologFlag = _rule.CurrentPrologFlag - -KtMember = _rule.Member - -Not = _rule.Not - -Once = _rule.Once - -KtSemicolon = _rule.Semicolon - -SetPrologFlag = _rule.SetPrologFlag - - -class Append: - FUNCTOR = KtAppend.FUNCTOR - - ARITY = KtAppend.ARITY - - SIGNATURE = signature(FUNCTOR, ARITY) - - Base = KtAppend.Base.INSTANCE - - Recursive = KtAppend.Recursive.INSTANCE - - -Arrow = Arrow.INSTANCE - -CurrentPrologFlag = CurrentPrologFlag.INSTANCE - - -class Member: - FUNCTOR = KtMember.FUNCTOR - - ARITY = KtMember.ARITY - - SIGNATURE = signature(FUNCTOR, ARITY) - - Base = KtMember.Base.INSTANCE - - Recursive = KtMember.Recursive.INSTANCE - - -Not = Not.INSTANCE - -Once = Once.INSTANCE - - -class Semicolon: - FUNCTOR = KtSemicolon.FUNCTOR - - ARITY = KtSemicolon.ARITY - - SIGNATURE = signature(FUNCTOR, ARITY) - - class If: - Then = KtSemicolon.If.Then.INSTANCE - - Else = KtSemicolon.If.Else.INSTANCE - - class Or: - Left = KtSemicolon.Or.Left.INSTANCE - - Right = KtSemicolon.Or.Right.INSTANCE - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.stdlib.rule.*") From 805640a7974440e0be963cde0f7abab4c2c1a507 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 12 Oct 2023 13:27:45 +0200 Subject: [PATCH 132/154] Update prolog and problog packages --- test/solve/problog/test_problog_example.py | 2 +- tuprolog/__main__.py | 1 - tuprolog/solve/problog/__init__.py | 40 +------------------ tuprolog/solve/problog/_api.py | 28 +++++++++++++ .../problog/{operators.py => _definitions.py} | 11 ++++- tuprolog/solve/prolog/__init__.py | 39 +----------------- tuprolog/solve/prolog/_api.py | 27 +++++++++++++ tuprolog/solve/prolog/_definitions.py | 8 ++++ 8 files changed, 78 insertions(+), 78 deletions(-) create mode 100644 tuprolog/solve/problog/_api.py rename tuprolog/solve/problog/{operators.py => _definitions.py} (76%) create mode 100644 tuprolog/solve/prolog/_api.py create mode 100644 tuprolog/solve/prolog/_definitions.py diff --git a/test/solve/problog/test_problog_example.py b/test/solve/problog/test_problog_example.py index d312098..e16fae2 100644 --- a/test/solve/problog/test_problog_example.py +++ b/test/solve/problog/test_problog_example.py @@ -3,7 +3,7 @@ from tuprolog.theory.parsing import parse_theory from tuprolog.solve.plp import solve_options, probability from tuprolog.solve.problog import problog_solver -from tuprolog.solve.problog.operators import PROBLOG_OPERATORS +from tuprolog.solve.problog import PROBLOG_OPERATORS class ExemplifyProblog(unittest.TestCase): diff --git a/tuprolog/__main__.py b/tuprolog/__main__.py index fd552e1..c6cb5c9 100644 --- a/tuprolog/__main__.py +++ b/tuprolog/__main__.py @@ -28,7 +28,6 @@ from tuprolog.solve.prolog import * from tuprolog.solve.plp import * from tuprolog.solve.problog import * -from tuprolog.solve.problog.operators import * import code diff --git a/tuprolog/solve/problog/__init__.py b/tuprolog/solve/problog/__init__.py index 64e658c..3272497 100644 --- a/tuprolog/solve/problog/__init__.py +++ b/tuprolog/solve/problog/__init__.py @@ -1,38 +1,2 @@ -from tuprolog import logger -from tuprolog.solve.flags import DEFAULT_FLAG_STORE, FlagStore -from tuprolog.solve.library import libraries, Library, Runtime -from tuprolog.solve.channel import InputChannel, OutputChannel, std_out, std_in, std_err, warn -from tuprolog.theory import theory, mutable_theory, Theory, Unificator -from tuprolog.solve import Solver, SolverFactory - - -_PROBLOG_SOLVER_FACTORY = Solver.problog() - - -def problog_solver( - unificator: Unificator = Unificator.getDefault(), - libraries: Library = libraries(), - flags: FlagStore = DEFAULT_FLAG_STORE, - static_kb: Theory = theory(), - dynamic_kb: Theory = mutable_theory(), - std_in: InputChannel = std_in(), - std_out: OutputChannel = std_out(), - std_err: OutputChannel = std_err(), - warning: OutputChannel = warn(), - mutable: bool = True -) -> Solver: - if mutable: - return _PROBLOG_SOLVER_FACTORY.mutableSolverWithDefaultBuiltins( - unificator, Runtime.of(libraries), flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning - ) - else: - return _PROBLOG_SOLVER_FACTORY.solverWithDefaultBuiltins( - unificator, Runtime.of(libraries), flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning - ) - - -def problog_solver_factory() -> SolverFactory: - return _PROBLOG_SOLVER_FACTORY - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.problog.*") +from ._definitions import * +from ._api import * diff --git a/tuprolog/solve/problog/_api.py b/tuprolog/solve/problog/_api.py new file mode 100644 index 0000000..13ad3d4 --- /dev/null +++ b/tuprolog/solve/problog/_api.py @@ -0,0 +1,28 @@ +from tuprolog.solve import Solver +from tuprolog.solve.flags import DEFAULT_FLAG_STORE, FlagStore +from tuprolog.solve.library import libraries, Library, Runtime +from tuprolog.solve.channel import InputChannel, OutputChannel, std_out, std_in, std_err, warn +from tuprolog.theory import theory, mutable_theory, Theory, Unificator +from ._definitions import PROBLOG_SOLVER_FACTORY + + +def problog_solver( + unificator: Unificator = Unificator.getDefault(), + libraries: Library = libraries(), + flags: FlagStore = DEFAULT_FLAG_STORE, + static_kb: Theory = theory(), + dynamic_kb: Theory = mutable_theory(), + std_in: InputChannel = std_in(), + std_out: OutputChannel = std_out(), + std_err: OutputChannel = std_err(), + warning: OutputChannel = warn(), + mutable: bool = True +) -> Solver: + if mutable: + return PROBLOG_SOLVER_FACTORY.mutableSolverWithDefaultBuiltins( + unificator, Runtime.of(libraries), flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning + ) + else: + return PROBLOG_SOLVER_FACTORY.solverWithDefaultBuiltins( + unificator, Runtime.of(libraries), flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning + ) diff --git a/tuprolog/solve/problog/operators.py b/tuprolog/solve/problog/_definitions.py similarity index 76% rename from tuprolog/solve/problog/operators.py rename to tuprolog/solve/problog/_definitions.py index 34619be..70e62f3 100644 --- a/tuprolog/solve/problog/operators.py +++ b/tuprolog/solve/problog/_definitions.py @@ -1,13 +1,22 @@ from tuprolog import logger +from tuprolog.solve import Solver, SolverFactory import jpype.imports # noqa: F401 import it.unibo.tuprolog.solve.problog as _problog # type: ignore + +PROBLOG_SOLVER_FACTORY : SolverFactory = Solver.problog() + + Operators = _problog.Operators + ANNOTATION_OPERATOR = Operators.ANNOTATION_OPERATOR + PROBLOG_SPECIFIC_OPERATORS = Operators.PROBLOG_SPECIFIC_OPERATORS + PROBLOG_OPERATORS = Operators.PROBLOG_OPERATORS -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.problog.operators") + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.problog.*") diff --git a/tuprolog/solve/prolog/__init__.py b/tuprolog/solve/prolog/__init__.py index 97636d7..8151d30 100644 --- a/tuprolog/solve/prolog/__init__.py +++ b/tuprolog/solve/prolog/__init__.py @@ -1,37 +1,2 @@ -from tuprolog import logger -from tuprolog.solve.flags import DEFAULT_FLAG_STORE, FlagStore -from tuprolog.solve.library import libraries, Library -from tuprolog.solve.channel import InputChannel, OutputChannel, std_out, std_in, std_err, warn -from tuprolog.theory import theory, mutable_theory, Theory -from tuprolog.solve import Solver, SolverFactory - - -_PROLOG_SOLVER_FACTORY = Solver.prolog() - - -def prolog_solver( - libraries: Library = libraries(), - flags: FlagStore = DEFAULT_FLAG_STORE, - static_kb: Theory = theory(), - dynamic_kb: Theory = mutable_theory(), - std_in: InputChannel = std_in(), - std_out: OutputChannel = std_out(), - std_err: OutputChannel = std_err(), - warning: OutputChannel = warn(), - mutable: bool = True -) -> Solver: - if mutable: - return _PROLOG_SOLVER_FACTORY.mutableSolverWithDefaultBuiltins( - libraries, flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning - ) - else: - return _PROLOG_SOLVER_FACTORY.solverWithDefaultBuiltins( - libraries, flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning - ) - - -def prolog_solver_factory() -> SolverFactory: - return _PROLOG_SOLVER_FACTORY - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.prolog.*") +from ._definitions import PROLOG_SOLVER_FACTORY +from ._api import prolog_solver diff --git a/tuprolog/solve/prolog/_api.py b/tuprolog/solve/prolog/_api.py new file mode 100644 index 0000000..7324c42 --- /dev/null +++ b/tuprolog/solve/prolog/_api.py @@ -0,0 +1,27 @@ +from tuprolog.solve import Solver +from tuprolog.solve.flags import DEFAULT_FLAG_STORE, FlagStore +from tuprolog.solve.library import libraries, Library +from tuprolog.solve.channel import InputChannel, OutputChannel, std_out, std_in, std_err, warn +from tuprolog.theory import theory, mutable_theory, Theory +from ._definitions import PROLOG_SOLVER_FACTORY + + +def prolog_solver( + libraries: Library = libraries(), + flags: FlagStore = DEFAULT_FLAG_STORE, + static_kb: Theory = theory(), + dynamic_kb: Theory = mutable_theory(), + std_in: InputChannel = std_in(), + std_out: OutputChannel = std_out(), + std_err: OutputChannel = std_err(), + warning: OutputChannel = warn(), + mutable: bool = True +) -> Solver: + if mutable: + return PROLOG_SOLVER_FACTORY.mutableSolverWithDefaultBuiltins( + libraries, flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning + ) + else: + return PROLOG_SOLVER_FACTORY.solverWithDefaultBuiltins( + libraries, flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning + ) diff --git a/tuprolog/solve/prolog/_definitions.py b/tuprolog/solve/prolog/_definitions.py new file mode 100644 index 0000000..a918dfe --- /dev/null +++ b/tuprolog/solve/prolog/_definitions.py @@ -0,0 +1,8 @@ +from tuprolog import logger +from tuprolog.solve import Solver, SolverFactory + + +PROLOG_SOLVER_FACTORY : SolverFactory = Solver.prolog() + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.prolog.*") From 960bf99b87236b29af835124b04198ba95c0f191 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 12 Oct 2023 14:09:06 +0200 Subject: [PATCH 133/154] Import parsing modules --- tuprolog/core/operators/__init__.py | 70 +-------- .../operators/{_ktadapt.py => _adapters.py} | 0 tuprolog/core/operators/_api.py | 34 +++++ tuprolog/core/operators/_definitions.py | 45 ++++++ tuprolog/core/parsing/__init__.py | 92 +----------- .../parsing/{_ktadapt.py => _adapters.py} | 0 tuprolog/core/parsing/_api.py | 70 +++++++++ tuprolog/core/parsing/_definitions.py | 23 +++ tuprolog/solve/problog/_definitions.py | 2 +- tuprolog/solve/prolog/_definitions.py | 2 +- tuprolog/solve/stdlib/_definitions.py | 8 +- tuprolog/solve/stdlib/magic.py | 2 +- tuprolog/solve/stdlib/primitive.py | 139 +++++++++--------- tuprolog/solve/stdlib/rule.py | 10 +- tuprolog/theory/parsing/__init__.py | 56 +------ .../parsing/{_ktadapt.py => _adapters.py} | 0 tuprolog/theory/parsing/_api.py | 37 +++++ tuprolog/theory/parsing/_definitions.py | 18 +++ 18 files changed, 317 insertions(+), 291 deletions(-) rename tuprolog/core/operators/{_ktadapt.py => _adapters.py} (100%) create mode 100644 tuprolog/core/operators/_api.py create mode 100644 tuprolog/core/operators/_definitions.py rename tuprolog/core/parsing/{_ktadapt.py => _adapters.py} (100%) create mode 100644 tuprolog/core/parsing/_api.py create mode 100644 tuprolog/core/parsing/_definitions.py rename tuprolog/theory/parsing/{_ktadapt.py => _adapters.py} (100%) create mode 100644 tuprolog/theory/parsing/_api.py create mode 100644 tuprolog/theory/parsing/_definitions.py diff --git a/tuprolog/core/operators/__init__.py b/tuprolog/core/operators/__init__.py index 9f2c6e8..501ec39 100644 --- a/tuprolog/core/operators/__init__.py +++ b/tuprolog/core/operators/__init__.py @@ -1,67 +1,3 @@ -from functools import singledispatch -from tuprolog import logger -from tuprolog.jvmutils import jiterable -from tuprolog.pyutils import iterable_or_varargs -from tuprolog.core import Atom, Integer, Struct, Term -from ._ktadapt import * -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.core.operators as _operators # type: ignore - -Operator = _operators.Operator - -OperatorSet = _operators.OperatorSet - -Specifier = _operators.Specifier - - -@singledispatch -def operator(functor: str, specifier: Specifier, priority: int) -> Operator: - return Operator(functor, specifier, priority) - - -@operator.register -def _(priority: Integer, specifier: Atom, functor: Atom) -> Operator: - return Operator.fromTerms(priority, specifier, functor) - - -@operator.register -def _(term: Struct) -> Operator: - return Operator.fromTerm(term) - - -def operator_set(*operators) -> OperatorSet: - return iterable_or_varargs(operators, lambda os: OperatorSet(jiterable(os))) - - -@singledispatch -def specifier(name: str) -> Specifier: - return Specifier.valueOf(name.upper()) - - -@specifier.register -def _(term: Term) -> Specifier: - return Specifier.fromTerm(term) - - -EMPTY_OPERATORS: OperatorSet = OperatorSet.EMPTY - -DEFAULT_OPERATORS: OperatorSet = OperatorSet.DEFAULT - -STANDARD_OPERATORS: OperatorSet = OperatorSet.STANDARD - -XF: Specifier = Specifier.XF - -YF: Specifier = Specifier.YF - -FX: Specifier = Specifier.FX - -FY: Specifier = Specifier.FY - -XFX: Specifier = Specifier.XFX - -XFY: Specifier = Specifier.XFY - -YFX: Specifier = Specifier.YFX - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.core.operators.*") +import tuprolog.core.operators._adapters as _ +from ._definitions import * +from ._api import * diff --git a/tuprolog/core/operators/_ktadapt.py b/tuprolog/core/operators/_adapters.py similarity index 100% rename from tuprolog/core/operators/_ktadapt.py rename to tuprolog/core/operators/_adapters.py diff --git a/tuprolog/core/operators/_api.py b/tuprolog/core/operators/_api.py new file mode 100644 index 0000000..48b87dc --- /dev/null +++ b/tuprolog/core/operators/_api.py @@ -0,0 +1,34 @@ +from functools import singledispatch +from tuprolog.jvmutils import jiterable +from tuprolog.pyutils import iterable_or_varargs +from tuprolog.core import Atom, Integer, Struct, Term +from ._definitions import Operator, OperatorSet, Specifier + + +@singledispatch +def operator(functor: str, specifier: Specifier, priority: int) -> Operator: + return Operator(functor, specifier, priority) + + +@operator.register +def _(priority: Integer, specifier: Atom, functor: Atom) -> Operator: + return Operator.fromTerms(priority, specifier, functor) + + +@operator.register +def _(term: Struct) -> Operator: + return Operator.fromTerm(term) + + +def operator_set(*operators) -> OperatorSet: + return iterable_or_varargs(operators, lambda os: OperatorSet(jiterable(os))) + + +@singledispatch +def specifier(name: str) -> Specifier: + return Specifier.valueOf(name.upper()) + + +@specifier.register +def _(term: Term) -> Specifier: + return Specifier.fromTerm(term) diff --git a/tuprolog/core/operators/_definitions.py b/tuprolog/core/operators/_definitions.py new file mode 100644 index 0000000..c168015 --- /dev/null +++ b/tuprolog/core/operators/_definitions.py @@ -0,0 +1,45 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.core.operators as _operators # type: ignore + + +Operator = _operators.Operator + + +OperatorSet = _operators.OperatorSet + + +Specifier = _operators.Specifier + + +EMPTY_OPERATORS: OperatorSet = OperatorSet.EMPTY + + +DEFAULT_OPERATORS: OperatorSet = OperatorSet.DEFAULT + + +STANDARD_OPERATORS: OperatorSet = OperatorSet.STANDARD + + +XF: Specifier = Specifier.XF + + +YF: Specifier = Specifier.YF + + +FX: Specifier = Specifier.FX + + +FY: Specifier = Specifier.FY + + +XFX: Specifier = Specifier.XFX + + +XFY: Specifier = Specifier.XFY + + +YFX: Specifier = Specifier.YFX + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.core.operators.*") diff --git a/tuprolog/core/parsing/__init__.py b/tuprolog/core/parsing/__init__.py index 18683f4..f014f62 100644 --- a/tuprolog/core/parsing/__init__.py +++ b/tuprolog/core/parsing/__init__.py @@ -1,89 +1,3 @@ -from typing import Union, Iterable -from tuprolog import logger -from tuprolog.jvmioutils import InputStream -from tuprolog.core import Term, Struct, Constant, Var, Atom, Numeric, Integer, Real, Clause -from tuprolog.core.operators import OperatorSet, DEFAULT_OPERATORS -from ._ktadapt import * -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.core.parsing as _parsing # type: ignore - -TermParser = _parsing.TermParser - -TermReader = _parsing.TermReader - -ParseException = _parsing.ParseException - -InvalidTermTypeException = _parsing.InvalidTermTypeException - - -def _factory(source, with_default_operators: bool = True, operators: OperatorSet = None): - if operators is None: - if with_default_operators: - return source.withDefaultOperators() - else: - return source.withNoOperator() - else: - if with_default_operators: - return source.withOperators(DEFAULT_OPERATORS.plus(operators)) - else: - return source.withOperators(operators) - - -def term_parser(with_default_operators: bool = True, operators: OperatorSet = None) -> TermParser: - return _factory(TermParser, with_default_operators, operators) - - -def term_reader(with_default_operators: bool = True, operators: OperatorSet = None) -> TermParser: - return _factory(TermReader, with_default_operators, operators) - - -DEFAULT_TERM_PARSER = term_parser() - -DEFAULT_TERM_READER = term_reader() - - -def parse_term(string: str, operators: OperatorSet = None) -> Term: - return DEFAULT_TERM_PARSER.parse_term(string, operators) - - -def parse_struct(string: str, operators: OperatorSet = None) -> Struct: - return DEFAULT_TERM_PARSER.parse_struct(string, operators) - - -def parse_constant(string: str, operators: OperatorSet = None) -> Constant: - return DEFAULT_TERM_PARSER.parse_constant(string, operators) - - -def parse_var(string: str, operators: OperatorSet = None) -> Var: - return DEFAULT_TERM_PARSER.parse_var(string, operators) - - -def parse_atom(string: str, operators: OperatorSet = None) -> Atom: - return DEFAULT_TERM_PARSER.parse_atom(string, operators) - - -def parse_numeric(string: str, operators: OperatorSet = None) -> Numeric: - return DEFAULT_TERM_PARSER.parse_numeric(string, operators) - - -def parse_integer(string: str, operators: OperatorSet = None) -> Integer: - return DEFAULT_TERM_PARSER.parse_integer(string, operators) - - -def parse_real(string: str, operators: OperatorSet = None) -> Real: - return DEFAULT_TERM_PARSER.parse_real(string, operators) - - -def parse_clause(string: str, operators: OperatorSet = None) -> Clause: - return DEFAULT_TERM_PARSER.parse_clause(string, operators) - - -def read_term(input: Union[InputStream, str], operators: OperatorSet = None) -> Term: - return DEFAULT_TERM_READER.read_term(input, operators) - - -def read_terms(input: Union[InputStream, str], operators: OperatorSet = None) -> Iterable[Term]: - return DEFAULT_TERM_READER.read_terms(input, operators) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.core.parsing.*") +import tuprolog.core.parsing._adapters as _ +from ._definitions import * +from ._api import * diff --git a/tuprolog/core/parsing/_ktadapt.py b/tuprolog/core/parsing/_adapters.py similarity index 100% rename from tuprolog/core/parsing/_ktadapt.py rename to tuprolog/core/parsing/_adapters.py diff --git a/tuprolog/core/parsing/_api.py b/tuprolog/core/parsing/_api.py new file mode 100644 index 0000000..a727e31 --- /dev/null +++ b/tuprolog/core/parsing/_api.py @@ -0,0 +1,70 @@ +from typing import Union, Iterable +from tuprolog.jvmioutils import InputStream +from tuprolog.core import Term, Struct, Constant, Var, Atom, Numeric, Integer, Real, Clause +from tuprolog.core.operators import OperatorSet, DEFAULT_OPERATORS +from ._definitions import TermParser, TermReader, DEFAULT_TERM_PARSER, DEFAULT_TERM_READER + + +def parser_factory(source, with_default_operators: bool = True, operators: OperatorSet = None): + if operators is None: + if with_default_operators: + return source.withDefaultOperators() + else: + return source.withNoOperator() + else: + if with_default_operators: + return source.withOperators(DEFAULT_OPERATORS.plus(operators)) + else: + return source.withOperators(operators) + + +def term_parser(with_default_operators: bool = True, operators: OperatorSet = None) -> TermParser: + return parser_factory(TermParser, with_default_operators, operators) + + +def term_reader(with_default_operators: bool = True, operators: OperatorSet = None) -> TermParser: + return parser_factory(TermReader, with_default_operators, operators) + + +def parse_term(string: str, operators: OperatorSet = None) -> Term: + return DEFAULT_TERM_PARSER.parse_term(string, operators) + + +def parse_struct(string: str, operators: OperatorSet = None) -> Struct: + return DEFAULT_TERM_PARSER.parse_struct(string, operators) + + +def parse_constant(string: str, operators: OperatorSet = None) -> Constant: + return DEFAULT_TERM_PARSER.parse_constant(string, operators) + + +def parse_var(string: str, operators: OperatorSet = None) -> Var: + return DEFAULT_TERM_PARSER.parse_var(string, operators) + + +def parse_atom(string: str, operators: OperatorSet = None) -> Atom: + return DEFAULT_TERM_PARSER.parse_atom(string, operators) + + +def parse_numeric(string: str, operators: OperatorSet = None) -> Numeric: + return DEFAULT_TERM_PARSER.parse_numeric(string, operators) + + +def parse_integer(string: str, operators: OperatorSet = None) -> Integer: + return DEFAULT_TERM_PARSER.parse_integer(string, operators) + + +def parse_real(string: str, operators: OperatorSet = None) -> Real: + return DEFAULT_TERM_PARSER.parse_real(string, operators) + + +def parse_clause(string: str, operators: OperatorSet = None) -> Clause: + return DEFAULT_TERM_PARSER.parse_clause(string, operators) + + +def read_term(input: Union[InputStream, str], operators: OperatorSet = None) -> Term: + return DEFAULT_TERM_READER.read_term(input, operators) + + +def read_terms(input: Union[InputStream, str], operators: OperatorSet = None) -> Iterable[Term]: + return DEFAULT_TERM_READER.read_terms(input, operators) diff --git a/tuprolog/core/parsing/_definitions.py b/tuprolog/core/parsing/_definitions.py new file mode 100644 index 0000000..e1a795f --- /dev/null +++ b/tuprolog/core/parsing/_definitions.py @@ -0,0 +1,23 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.core.parsing as _parsing # type: ignore + +TermParser = _parsing.TermParser + + +TermReader = _parsing.TermReader + + +ParseException = _parsing.ParseException + + +InvalidTermTypeException = _parsing.InvalidTermTypeException + + +DEFAULT_TERM_PARSER = TermParser.withDefaultOperators() + + +DEFAULT_TERM_READER = TermReader.withDefaultOperators() + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.core.parsing.*") diff --git a/tuprolog/solve/problog/_definitions.py b/tuprolog/solve/problog/_definitions.py index 70e62f3..580fa36 100644 --- a/tuprolog/solve/problog/_definitions.py +++ b/tuprolog/solve/problog/_definitions.py @@ -4,7 +4,7 @@ import it.unibo.tuprolog.solve.problog as _problog # type: ignore -PROBLOG_SOLVER_FACTORY : SolverFactory = Solver.problog() +PROBLOG_SOLVER_FACTORY: SolverFactory = Solver.problog() Operators = _problog.Operators diff --git a/tuprolog/solve/prolog/_definitions.py b/tuprolog/solve/prolog/_definitions.py index a918dfe..b3fe98c 100644 --- a/tuprolog/solve/prolog/_definitions.py +++ b/tuprolog/solve/prolog/_definitions.py @@ -2,7 +2,7 @@ from tuprolog.solve import Solver, SolverFactory -PROLOG_SOLVER_FACTORY : SolverFactory = Solver.prolog() +PROLOG_SOLVER_FACTORY: SolverFactory = Solver.prolog() logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.prolog.*") diff --git a/tuprolog/solve/stdlib/_definitions.py b/tuprolog/solve/stdlib/_definitions.py index 2b0ac89..0ec64a0 100644 --- a/tuprolog/solve/stdlib/_definitions.py +++ b/tuprolog/solve/stdlib/_definitions.py @@ -3,16 +3,16 @@ import it.unibo.tuprolog.solve.stdlib as _stdlib # type: ignore -CommonBuiltins : _stdlib.CommonBuiltins = _stdlib.CommonBuiltins.INSTANCE +CommonBuiltins: _stdlib.CommonBuiltins = _stdlib.CommonBuiltins.INSTANCE -CommonFunctions : _stdlib.CommonFunctions = _stdlib.CommonFunctions.INSTANCE +CommonFunctions: _stdlib.CommonFunctions = _stdlib.CommonFunctions.INSTANCE -CommonPrimitives : _stdlib.CommonPrimitives = _stdlib.CommonPrimitives.INSTANCE +CommonPrimitives: _stdlib.CommonPrimitives = _stdlib.CommonPrimitives.INSTANCE -CommonRules : _stdlib.CommonRules = _stdlib.CommonRules.INSTANCE +CommonRules: _stdlib.CommonRules = _stdlib.CommonRules.INSTANCE logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.stdlib.*") diff --git a/tuprolog/solve/stdlib/magic.py b/tuprolog/solve/stdlib/magic.py index 7f82376..d012dae 100644 --- a/tuprolog/solve/stdlib/magic.py +++ b/tuprolog/solve/stdlib/magic.py @@ -3,7 +3,7 @@ import it.unibo.tuprolog.solve.stdlib.magic as _magic # type: ignore -MagicCut : _magic.MagicCut = _magic.MagicCut.INSTANCE +MagicCut: _magic.MagicCut = _magic.MagicCut.INSTANCE logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.stdlib.magic.*") diff --git a/tuprolog/solve/stdlib/primitive.py b/tuprolog/solve/stdlib/primitive.py index 6b249ac..b6e9dd4 100644 --- a/tuprolog/solve/stdlib/primitive.py +++ b/tuprolog/solve/stdlib/primitive.py @@ -3,212 +3,211 @@ import it.unibo.tuprolog.solve.stdlib.primitive as _primitive # type: ignore -Abolish : _primitive.Abolish = _primitive.Abolish.INSTANCE +Abolish: _primitive.Abolish = _primitive.Abolish.INSTANCE -Arg : _primitive.Arg = _primitive.Arg.INSTANCE +Arg: _primitive.Arg = _primitive.Arg.INSTANCE -ArithmeticEqual : _primitive.ArithmeticEqual = _primitive.ArithmeticEqual.INSTANCE +ArithmeticEqual: _primitive.ArithmeticEqual = _primitive.ArithmeticEqual.INSTANCE -ArithmeticGreaterThan : _primitive.ArithmeticGreaterThan = _primitive.ArithmeticGreaterThan.INSTANCE +ArithmeticGreaterThan: _primitive.ArithmeticGreaterThan = _primitive.ArithmeticGreaterThan.INSTANCE -ArithmeticGreaterThanOrEqualTo : _primitive.ArithmeticGreaterThanOrEqualTo = _primitive.ArithmeticGreaterThanOrEqualTo.INSTANCE +ArithmeticGreaterThanOrEqualTo: _primitive.ArithmeticGreaterThanOrEqualTo = _primitive.ArithmeticGreaterThanOrEqualTo.INSTANCE -ArithmeticLowerThan : _primitive.ArithmeticLowerThan = _primitive.ArithmeticLowerThan.INSTANCE +ArithmeticLowerThan: _primitive.ArithmeticLowerThan = _primitive.ArithmeticLowerThan.INSTANCE -ArithmeticLowerThanOrEqualTo : _primitive.ArithmeticLowerThanOrEqualTo = _primitive.ArithmeticLowerThanOrEqualTo.INSTANCE +ArithmeticLowerThanOrEqualTo: _primitive.ArithmeticLowerThanOrEqualTo = _primitive.ArithmeticLowerThanOrEqualTo.INSTANCE -ArithmeticNotEqual : _primitive.ArithmeticNotEqual = _primitive.ArithmeticNotEqual.INSTANCE +ArithmeticNotEqual: _primitive.ArithmeticNotEqual = _primitive.ArithmeticNotEqual.INSTANCE -Assert : _primitive.Assert = _primitive.Assert.INSTANCE +Assert: _primitive.Assert = _primitive.Assert.INSTANCE -AssertA : _primitive.AssertA = _primitive.AssertA.INSTANCE +AssertA: _primitive.AssertA = _primitive.AssertA.INSTANCE -AssertZ : _primitive.AssertZ = _primitive.AssertZ.INSTANCE +AssertZ: _primitive.AssertZ = _primitive.AssertZ.INSTANCE -Atom : _primitive.Atom = _primitive.Atom.INSTANCE +Atom: _primitive.Atom = _primitive.Atom.INSTANCE -AtomChars : _primitive.AtomChars = _primitive.AtomChars.INSTANCE +AtomChars: _primitive.AtomChars = _primitive.AtomChars.INSTANCE -AtomCodes : _primitive.AtomCodes = _primitive.AtomCodes.INSTANCE +AtomCodes: _primitive.AtomCodes = _primitive.AtomCodes.INSTANCE -AtomConcat : _primitive.AtomConcat = _primitive.AtomConcat.INSTANCE +AtomConcat: _primitive.AtomConcat = _primitive.AtomConcat.INSTANCE -AtomLength : _primitive.AtomLength = _primitive.AtomLength.INSTANCE +AtomLength: _primitive.AtomLength = _primitive.AtomLength.INSTANCE -Atomic : _primitive.Atomic = _primitive.Atomic.INSTANCE +Atomic: _primitive.Atomic = _primitive.Atomic.INSTANCE -BagOf : _primitive.BagOf = _primitive.BagOf.INSTANCE +BagOf: _primitive.BagOf = _primitive.BagOf.INSTANCE -Between : _primitive.Between = _primitive.Between.INSTANCE +Between: _primitive.Between = _primitive.Between.INSTANCE -Callable : _primitive.Callable = _primitive.Callable.INSTANCE +Callable: _primitive.Callable = _primitive.Callable.INSTANCE -CharCode : _primitive.CharCode = _primitive.CharCode.INSTANCE +CharCode: _primitive.CharCode = _primitive.CharCode.INSTANCE -Clause : _primitive.Clause = _primitive.Clause.INSTANCE +Clause: _primitive.Clause = _primitive.Clause.INSTANCE -Compound : _primitive.Compound = _primitive.Compound.INSTANCE +Compound: _primitive.Compound = _primitive.Compound.INSTANCE -CopyTerm : _primitive.CopyTerm = _primitive.CopyTerm.INSTANCE +CopyTerm: _primitive.CopyTerm = _primitive.CopyTerm.INSTANCE -CurrentFlag : _primitive.CurrentFlag = _primitive.CurrentFlag.INSTANCE +CurrentFlag: _primitive.CurrentFlag = _primitive.CurrentFlag.INSTANCE -CurrentOp : _primitive.CurrentOp = _primitive.CurrentOp.INSTANCE +CurrentOp: _primitive.CurrentOp = _primitive.CurrentOp.INSTANCE -EnsureExecutable : _primitive.EnsureExecutable = _primitive.EnsureExecutable.INSTANCE +EnsureExecutable: _primitive.EnsureExecutable = _primitive.EnsureExecutable.INSTANCE -FindAll : _primitive.FindAll = _primitive.FindAll.INSTANCE +FindAll: _primitive.FindAll = _primitive.FindAll.INSTANCE -Float : _primitive.Float = _primitive.Float.INSTANCE +Float: _primitive.Float = _primitive.Float.INSTANCE -Functor : _primitive.Functor = _primitive.Functor.INSTANCE +Functor: _primitive.Functor = _primitive.Functor.INSTANCE -GetDurable : _primitive.GetDurable = _primitive.GetDurable.INSTANCE +GetDurable: _primitive.GetDurable = _primitive.GetDurable.INSTANCE -GetEphemeral : _primitive.GetEphemeral = _primitive.GetEphemeral.INSTANCE +GetEphemeral: _primitive.GetEphemeral = _primitive.GetEphemeral.INSTANCE -GetPersistent : _primitive.GetPersistent = _primitive.GetPersistent.INSTANCE +GetPersistent: _primitive.GetPersistent = _primitive.GetPersistent.INSTANCE -Ground : _primitive.Ground = _primitive.Ground.INSTANCE +Ground: _primitive.Ground = _primitive.Ground.INSTANCE -Halt : _primitive.Halt = _primitive.Halt.INSTANCE +Halt: _primitive.Halt = _primitive.Halt.INSTANCE -Halt1 : _primitive.Halt1 = _primitive.Halt1.INSTANCE +Halt1: _primitive.Halt1 = _primitive.Halt1.INSTANCE -Integer : _primitive.Integer = _primitive.Integer.INSTANCE +Integer: _primitive.Integer = _primitive.Integer.INSTANCE -Is : _primitive.Is = _primitive.Is.INSTANCE +Is: _primitive.Is = _primitive.Is.INSTANCE -Natural : _primitive.Natural = _primitive.Natural.INSTANCE +Natural: _primitive.Natural = _primitive.Natural.INSTANCE -NewLine : _primitive.NewLine = _primitive.NewLine.INSTANCE +NewLine: _primitive.NewLine = _primitive.NewLine.INSTANCE -NonVar : _primitive.NonVar = _primitive.NonVar.INSTANCE +NonVar: _primitive.NonVar = _primitive.NonVar.INSTANCE -NotUnifiableWith : _primitive.NotUnifiableWith = _primitive.NotUnifiableWith.INSTANCE +NotUnifiableWith: _primitive.NotUnifiableWith = _primitive.NotUnifiableWith.INSTANCE -Number : _primitive.Number = _primitive.Number.INSTANCE +Number: _primitive.Number = _primitive.Number.INSTANCE -NumberChars : _primitive.NumberChars = _primitive.NumberChars.INSTANCE +NumberChars: _primitive.NumberChars = _primitive.NumberChars.INSTANCE -NumberCodes : _primitive.NumberCodes = _primitive.NumberCodes.INSTANCE +NumberCodes: _primitive.NumberCodes = _primitive.NumberCodes.INSTANCE -Op : _primitive.Op = _primitive.Op.INSTANCE +Op: _primitive.Op = _primitive.Op.INSTANCE -Repeat : _primitive.Repeat = _primitive.Repeat.INSTANCE +Repeat: _primitive.Repeat = _primitive.Repeat.INSTANCE -Retract : _primitive.Retract = _primitive.Retract.INSTANCE +Retract: _primitive.Retract = _primitive.Retract.INSTANCE -RetractAll : _primitive.RetractAll = _primitive.RetractAll.INSTANCE +RetractAll: _primitive.RetractAll = _primitive.RetractAll.INSTANCE -Reverse : _primitive.Reverse = _primitive.Reverse.INSTANCE +Reverse: _primitive.Reverse = _primitive.Reverse.INSTANCE -SetDurable : _primitive.SetDurable = _primitive.SetDurable.INSTANCE +SetDurable: _primitive.SetDurable = _primitive.SetDurable.INSTANCE -SetEphemeral : _primitive.SetEphemeral = _primitive.SetEphemeral.INSTANCE +SetEphemeral: _primitive.SetEphemeral = _primitive.SetEphemeral.INSTANCE -SetFlag : _primitive.SetFlag = _primitive.SetFlag.INSTANCE +SetFlag: _primitive.SetFlag = _primitive.SetFlag.INSTANCE -SetOf : _primitive.SetOf = _primitive.SetOf.INSTANCE +SetOf: _primitive.SetOf = _primitive.SetOf.INSTANCE -SetPersistent : _primitive.SetPersistent = _primitive.SetPersistent.INSTANCE +SetPersistent: _primitive.SetPersistent = _primitive.SetPersistent.INSTANCE -Sleep : _primitive.Sleep = _primitive.Sleep.INSTANCE +Sleep: _primitive.Sleep = _primitive.Sleep.INSTANCE -SubAtom : _primitive.SubAtom = _primitive.SubAtom.INSTANCE +SubAtom: _primitive.SubAtom = _primitive.SubAtom.INSTANCE -TermGreaterThan : _primitive.TermGreaterThan = _primitive.TermGreaterThan.INSTANCE +TermGreaterThan: _primitive.TermGreaterThan = _primitive.TermGreaterThan.INSTANCE -TermGreaterThanOrEqualTo : _primitive.TermGreaterThanOrEqualTo = _primitive.TermGreaterThanOrEqualTo.INSTANCE +TermGreaterThanOrEqualTo: _primitive.TermGreaterThanOrEqualTo = _primitive.TermGreaterThanOrEqualTo.INSTANCE -TermIdentical : _primitive.TermIdentical = _primitive.TermIdentical.INSTANCE +TermIdentical: _primitive.TermIdentical = _primitive.TermIdentical.INSTANCE -TermLowerThan : _primitive.TermLowerThan = _primitive.TermLowerThan.INSTANCE +TermLowerThan: _primitive.TermLowerThan = _primitive.TermLowerThan.INSTANCE -TermLowerThanOrEqualTo : _primitive.TermLowerThanOrEqualTo = _primitive.TermLowerThanOrEqualTo.INSTANCE +TermLowerThanOrEqualTo: _primitive.TermLowerThanOrEqualTo = _primitive.TermLowerThanOrEqualTo.INSTANCE -TermNotIdentical : _primitive.TermNotIdentical = _primitive.TermNotIdentical.INSTANCE +TermNotIdentical: _primitive.TermNotIdentical = _primitive.TermNotIdentical.INSTANCE -TermNotSame : _primitive.TermNotSame = _primitive.TermNotSame.INSTANCE +TermNotSame: _primitive.TermNotSame = _primitive.TermNotSame.INSTANCE -TermSame : _primitive.TermSame = _primitive.TermSame.INSTANCE +TermSame: _primitive.TermSame = _primitive.TermSame.INSTANCE -UnifiesWith : _primitive.UnifiesWith = _primitive.UnifiesWith.INSTANCE +UnifiesWith: _primitive.UnifiesWith = _primitive.UnifiesWith.INSTANCE -Univ : _primitive.Univ = _primitive.Univ.INSTANCE +Univ: _primitive.Univ = _primitive.Univ.INSTANCE -Var : _primitive.Var = _primitive.Var.INSTANCE +Var: _primitive.Var = _primitive.Var.INSTANCE -Write : _primitive.Write = _primitive.Write.INSTANCE - +Write: _primitive.Write = _primitive.Write.INSTANCE logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.stdlib.primitive.*") diff --git a/tuprolog/solve/stdlib/rule.py b/tuprolog/solve/stdlib/rule.py index 4182f1c..88b5b9a 100644 --- a/tuprolog/solve/stdlib/rule.py +++ b/tuprolog/solve/stdlib/rule.py @@ -19,10 +19,10 @@ class Append: Recursive = _Append.Recursive.INSTANCE -Arrow : _rule.Arrow = _rule.Arrow.INSTANCE +Arrow: _rule.Arrow = _rule.Arrow.INSTANCE -CurrentPrologFlag : _rule.CurrentPrologFlag = _rule.CurrentPrologFlag.INSTANCE +CurrentPrologFlag: _rule.CurrentPrologFlag = _rule.CurrentPrologFlag.INSTANCE _Member = _rule.Member @@ -40,10 +40,10 @@ class Member: Recursive = _Member.Recursive.INSTANCE -Not : _rule.Not = _rule.Not.INSTANCE +Not: _rule.Not = _rule.Not.INSTANCE -Once : _rule.Once = _rule.Once.INSTANCE +Once: _rule.Once = _rule.Once.INSTANCE _Semicolon = _rule.Semicolon @@ -67,7 +67,7 @@ class Or: Right = _Semicolon.Or.Right.INSTANCE -SetPrologFlag : _rule.SetPrologFlag = _rule.SetPrologFlag.INSTANCE +SetPrologFlag: _rule.SetPrologFlag = _rule.SetPrologFlag.INSTANCE logger.debug("Loaded JVM classes from it.unibo.tuprolog.solve.stdlib.rule.*") diff --git a/tuprolog/theory/parsing/__init__.py b/tuprolog/theory/parsing/__init__.py index e9e227d..be8a174 100644 --- a/tuprolog/theory/parsing/__init__.py +++ b/tuprolog/theory/parsing/__init__.py @@ -1,53 +1,3 @@ -from typing import Union, Iterable -from tuprolog import logger -from tuprolog.core import Clause -from tuprolog.core.parsing import _factory -from tuprolog.theory import Theory -from tuprolog.jvmioutils import InputStream -from tuprolog.core.operators import OperatorSet -from ._ktadapt import * -import jpype.imports # noqa: F401 -import it.unibo.tuprolog.theory.parsing as _parsing # type: ignore - - -ClausesParser = _parsing.ClausesParser - -ClausesReader = _parsing.ClausesReader - - -def clauses_parser(with_default_operators: bool = True, operators: OperatorSet = None) -> ClausesParser: - return _factory(ClausesParser, with_default_operators, operators) - - -def clauses_reader(with_default_operators: bool = True, operators: OperatorSet = None) -> ClausesReader: - return _factory(ClausesReader, with_default_operators, operators) - - -DEFAULT_CLAUSES_PARSER = clauses_parser() - -DEFAULT_CLAUSES_READER = clauses_reader() - - -def parse_theory(string: str, operators: OperatorSet = None) -> Theory: - return DEFAULT_CLAUSES_PARSER.parse_theory(string, operators) - - -def parse_clauses(string: str, operators: OperatorSet = None, lazy: bool = True) -> Iterable[Clause]: - if lazy: - return DEFAULT_CLAUSES_PARSER.parse_clauses_lazily(string, operators) - else: - return DEFAULT_CLAUSES_PARSER.parse_clauses(string, operators) - - -def read_theory(input: Union[InputStream, str], operators: OperatorSet = None) -> Theory: - return DEFAULT_CLAUSES_READER.read_theory(input, operators) - - -def read_clauses(input: Union[InputStream, str], operators: OperatorSet = None, lazy: bool = True) -> Iterable[Clause]: - if lazy: - return DEFAULT_CLAUSES_READER.read_clauses_lazily(input, operators) - else: - return DEFAULT_CLAUSES_READER.read_clauses(input, operators) - - -logger.debug("Loaded JVM classes from it.unibo.tuprolog.theory.parsing.*") +import tuprolog.theory.parsing._adapters as _ +from ._definitions import * +from ._api import * diff --git a/tuprolog/theory/parsing/_ktadapt.py b/tuprolog/theory/parsing/_adapters.py similarity index 100% rename from tuprolog/theory/parsing/_ktadapt.py rename to tuprolog/theory/parsing/_adapters.py diff --git a/tuprolog/theory/parsing/_api.py b/tuprolog/theory/parsing/_api.py new file mode 100644 index 0000000..2c71a37 --- /dev/null +++ b/tuprolog/theory/parsing/_api.py @@ -0,0 +1,37 @@ +from typing import Union, Iterable +from tuprolog.core import Clause +from tuprolog.core.parsing import parser_factory +from tuprolog.theory import Theory +from tuprolog.jvmioutils import InputStream +from tuprolog.core.operators import OperatorSet +from ._definitions import ClausesParser, ClausesReader, DEFAULT_CLAUSES_PARSER, DEFAULT_CLAUSES_READER + + +def clauses_parser(with_default_operators: bool = True, operators: OperatorSet = None) -> ClausesParser: + return parser_factory(ClausesParser, with_default_operators, operators) + + +def clauses_reader(with_default_operators: bool = True, operators: OperatorSet = None) -> ClausesReader: + return parser_factory(ClausesReader, with_default_operators, operators) + + +def parse_theory(string: str, operators: OperatorSet = None) -> Theory: + return DEFAULT_CLAUSES_PARSER.parse_theory(string, operators) + + +def parse_clauses(string: str, operators: OperatorSet = None, lazy: bool = True) -> Iterable[Clause]: + if lazy: + return DEFAULT_CLAUSES_PARSER.parse_clauses_lazily(string, operators) + else: + return DEFAULT_CLAUSES_PARSER.parse_clauses(string, operators) + + +def read_theory(input: Union[InputStream, str], operators: OperatorSet = None) -> Theory: + return DEFAULT_CLAUSES_READER.read_theory(input, operators) + + +def read_clauses(input: Union[InputStream, str], operators: OperatorSet = None, lazy: bool = True) -> Iterable[Clause]: + if lazy: + return DEFAULT_CLAUSES_READER.read_clauses_lazily(input, operators) + else: + return DEFAULT_CLAUSES_READER.read_clauses(input, operators) diff --git a/tuprolog/theory/parsing/_definitions.py b/tuprolog/theory/parsing/_definitions.py new file mode 100644 index 0000000..8daeedd --- /dev/null +++ b/tuprolog/theory/parsing/_definitions.py @@ -0,0 +1,18 @@ +from tuprolog import logger +import jpype.imports # noqa: F401 +import it.unibo.tuprolog.theory.parsing as _parsing # type: ignore + + +ClausesParser = _parsing.ClausesParser + + +ClausesReader = _parsing.ClausesReader + + +DEFAULT_CLAUSES_PARSER = ClausesParser.withDefaultOperators() + + +DEFAULT_CLAUSES_READER = ClausesReader.withDefaultOperators() + + +logger.debug("Loaded JVM classes from it.unibo.tuprolog.theory.parsing.*") From d1c2b07fc2a8ae6c397953a68e48a38fe52ee952 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 12 Oct 2023 18:54:14 +0200 Subject: [PATCH 134/154] Add tests --- ...log_example.py => test_problog_parsing.py} | 10 +-- test/solve/prolog/__init__.py | 0 test/{api => solve/prolog}/test_prolog.py | 16 +++-- test/solve/prolog/test_prolog_parsing.py | 65 +++++++++++++++++++ tuprolog/solve/flags/__init__.py | 1 + tuprolog/solve/flags/_adapters.py | 29 +++++++++ tuprolog/solve/prolog/_api.py | 9 +-- 7 files changed, 117 insertions(+), 13 deletions(-) rename test/solve/problog/{test_problog_example.py => test_problog_parsing.py} (82%) create mode 100644 test/solve/prolog/__init__.py rename test/{api => solve/prolog}/test_prolog.py (59%) create mode 100644 test/solve/prolog/test_prolog_parsing.py create mode 100644 tuprolog/solve/flags/_adapters.py diff --git a/test/solve/problog/test_problog_example.py b/test/solve/problog/test_problog_parsing.py similarity index 82% rename from test/solve/problog/test_problog_example.py rename to test/solve/problog/test_problog_parsing.py index e16fae2..2d6600c 100644 --- a/test/solve/problog/test_problog_example.py +++ b/test/solve/problog/test_problog_parsing.py @@ -6,10 +6,10 @@ from tuprolog.solve.problog import PROBLOG_OPERATORS -class ExemplifyProblog(unittest.TestCase): +class TestProblogWithParsingAndResolution(unittest.TestCase): def setUp(self) -> None: - self.probabilisticTheoryText = """ + self.theory_text = """ 0.6::edge(1,2). 0.1::edge(1,3). 0.4::edge(2,5). @@ -27,10 +27,10 @@ def print(self, message): self.prints.append(message) def test_problog(self): - probabilisticTheory = parse_theory(self.probabilisticTheoryText, PROBLOG_OPERATORS) - probabilisticSolver = problog_solver(static_kb=probabilisticTheory) + probabilistic_theory = parse_theory(self.theory_text, PROBLOG_OPERATORS) + solver = problog_solver(static_kb=probabilistic_theory) query = struct('path', var('From'), var('To')) - for solution in probabilisticSolver.solve(query, solve_options(lazy=True, probabilistic=True)): + for solution in solver.solve(query, solve_options(lazy=True, probabilistic=True)): if solution.is_yes: self.print(f"yes: {solution.solved_query} with probability {probability(solution)}") diff --git a/test/solve/prolog/__init__.py b/test/solve/prolog/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/api/test_prolog.py b/test/solve/prolog/test_prolog.py similarity index 59% rename from test/api/test_prolog.py rename to test/solve/prolog/test_prolog.py index 83a00ee..ee6f2d6 100644 --- a/test/api/test_prolog.py +++ b/test/solve/prolog/test_prolog.py @@ -1,10 +1,12 @@ import unittest from tuprolog.core import rule, struct, var, fact, atom +from tuprolog.theory import theory +from tuprolog.solve.prolog import prolog_solver class TestPrologWithResolution(unittest.TestCase): def test_abraham_family_tree(self): - program = [ + my_program = theory([ rule( struct("ancestor", var("X"), var("Y")), # :- struct("parent", var("X"), var("Y")), @@ -17,6 +19,12 @@ def test_abraham_family_tree(self): fact(struct("parent", atom("abraham"), atom("isaac"))), fact(struct("parent", atom("isaac"), atom("jacob"))), fact(struct("parent", atom("jacob"), atom("joseph"))), - ] - print(program) - # TODO: solve + ]) + solver = prolog_solver(static_kb=my_program) + who = var("Who") + query = struct("ancestor", atom("abraham"), who) + result = list[str]() + for solution in solver.solve(query): + if solution.is_yes: + result.append(str(solution.substitution[who])) + self.assertSequenceEqual(result, ["isaac", "jacob", "joseph"]) diff --git a/test/solve/prolog/test_prolog_parsing.py b/test/solve/prolog/test_prolog_parsing.py new file mode 100644 index 0000000..afb2e72 --- /dev/null +++ b/test/solve/prolog/test_prolog_parsing.py @@ -0,0 +1,65 @@ +import unittest +from tuprolog.core import struct, atom, integer +from tuprolog.theory.parsing import parse_theory +from tuprolog.solve.prolog import prolog_solver +from tuprolog.solve.flags import DEFAULT_FLAG_STORE, LastCallOptimization, FlagStore +from tuprolog.solve.channel import output_channel + + +class TestPrologWithParsingAndResolution(unittest.TestCase): + def setUp(self) -> None: + self.theory_text = """ + % Towers of Hanoi + move(1,X,Y,_) :- + write('Move top disk from '), + write(X), + write(' to '), + write(Y), + nl. + move(N,X,Y,Z) :- + N>1, + M is N-1, + move(M,X,Z,Y), + move(1,X,Y,_), + move(M,Z,Y,X). + """ + self.prints: list[str] = [] + self.maxDiff = None + + def print(self, message): + self.prints.append(message) + + def print_output(self, message): + message = str(message) + if len(self.prints) == 0: + self.prints.append(message) + elif self.prints[-1].endswith('\n'): + self.prints.append(message) + else: + self.prints[-1] += message + @unittest.skip("TODO: fix this test") + def test_prolog(self): + logic_theory = parse_theory(self.theory_text) + flags = DEFAULT_FLAG_STORE.set(LastCallOptimization, LastCallOptimization.OFF) + solver = prolog_solver( + static_kb=logic_theory, + flags=flags, + std_out=output_channel(self.print_output)) + query = struct("move", integer(3), atom("left"), atom("right"), atom("center")) + for solution in solver.solve(query): + if solution.is_yes: + self.print(f"yes: {solution.solved_query}") + + self.assertEqual( + self.prints, + [ + 'Move top disk from left to right\n', + 'Move top disk from left to center\n', + 'Move top disk from right to center\n', + 'Move top disk from left to right\n', + 'Move top disk from center to left\n', + 'Move top disk from center to right\n', + 'Move top disk from left to right\n', + 'yes: move(3, left, right, center)' + ] + ) \ No newline at end of file diff --git a/tuprolog/solve/flags/__init__.py b/tuprolog/solve/flags/__init__.py index 3272497..8467ebd 100644 --- a/tuprolog/solve/flags/__init__.py +++ b/tuprolog/solve/flags/__init__.py @@ -1,2 +1,3 @@ +import tuprolog.solve.flags._adapters as _ from ._definitions import * from ._api import * diff --git a/tuprolog/solve/flags/_adapters.py b/tuprolog/solve/flags/_adapters.py new file mode 100644 index 0000000..0194f54 --- /dev/null +++ b/tuprolog/solve/flags/_adapters.py @@ -0,0 +1,29 @@ +from jpype import JImplementationFor +from tuprolog import logger +from ._definitions import NotableFlag + + +@JImplementationFor("it.unibo.tuprolog.solve.flags.FlagStore") +class _KtFlagStore: + def __jclass_init__(cls): + pass + + def __len__(self): + return self.getSize() + + def __getitem__(self, notableFlag): + return self.get(notableFlag) + + def __setitem__(self, notableFlagName, notableFlag): + self.set(notableFlagName, notableFlag) + + def __add__(self, other): + return self.plus(other) + + def __sub__(self, other): + if isinstance(other, NotableFlag): + return self.minus(other.name) + return self.minus(other) + + +logger.debug("Configure Kotlin adapters for types in it.unibo.tuprolog.solve.flags.*") diff --git a/tuprolog/solve/prolog/_api.py b/tuprolog/solve/prolog/_api.py index 7324c42..6ead96c 100644 --- a/tuprolog/solve/prolog/_api.py +++ b/tuprolog/solve/prolog/_api.py @@ -1,12 +1,13 @@ from tuprolog.solve import Solver from tuprolog.solve.flags import DEFAULT_FLAG_STORE, FlagStore -from tuprolog.solve.library import libraries, Library +from tuprolog.solve.library import libraries, Library, Runtime from tuprolog.solve.channel import InputChannel, OutputChannel, std_out, std_in, std_err, warn -from tuprolog.theory import theory, mutable_theory, Theory +from tuprolog.theory import theory, mutable_theory, Theory, Unificator from ._definitions import PROLOG_SOLVER_FACTORY def prolog_solver( + unificator: Unificator = Unificator.getDefault(), libraries: Library = libraries(), flags: FlagStore = DEFAULT_FLAG_STORE, static_kb: Theory = theory(), @@ -19,9 +20,9 @@ def prolog_solver( ) -> Solver: if mutable: return PROLOG_SOLVER_FACTORY.mutableSolverWithDefaultBuiltins( - libraries, flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning + unificator, Runtime.of(libraries), flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning ) else: return PROLOG_SOLVER_FACTORY.solverWithDefaultBuiltins( - libraries, flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning + unificator, Runtime.of(libraries), flags, static_kb, dynamic_kb, std_in, std_out, std_err, warning ) From 875401d7401ebec5b08a5dac6cc5e85fdfba6ea9 Mon Sep 17 00:00:00 2001 From: Luca Deluigi Date: Fri, 13 Oct 2023 11:39:42 +0200 Subject: [PATCH 135/154] Fix flake complaints --- test/solve/prolog/test_prolog_parsing.py | 27 ++++++++++++------------ 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/test/solve/prolog/test_prolog_parsing.py b/test/solve/prolog/test_prolog_parsing.py index afb2e72..6b68310 100644 --- a/test/solve/prolog/test_prolog_parsing.py +++ b/test/solve/prolog/test_prolog_parsing.py @@ -2,7 +2,7 @@ from tuprolog.core import struct, atom, integer from tuprolog.theory.parsing import parse_theory from tuprolog.solve.prolog import prolog_solver -from tuprolog.solve.flags import DEFAULT_FLAG_STORE, LastCallOptimization, FlagStore +from tuprolog.solve.flags import DEFAULT_FLAG_STORE, LastCallOptimization from tuprolog.solve.channel import output_channel @@ -10,17 +10,17 @@ class TestPrologWithParsingAndResolution(unittest.TestCase): def setUp(self) -> None: self.theory_text = """ % Towers of Hanoi - move(1,X,Y,_) :- - write('Move top disk from '), - write(X), - write(' to '), - write(Y), - nl. - move(N,X,Y,Z) :- - N>1, - M is N-1, - move(M,X,Z,Y), - move(1,X,Y,_), + move(1,X,Y,_) :- + write('Move top disk from '), + write(X), + write(' to '), + write(Y), + nl. + move(N,X,Y,Z) :- + N>1, + M is N-1, + move(M,X,Z,Y), + move(1,X,Y,_), move(M,Z,Y,X). """ self.prints: list[str] = [] @@ -37,6 +37,7 @@ def print_output(self, message): self.prints.append(message) else: self.prints[-1] += message + @unittest.skip("TODO: fix this test") def test_prolog(self): logic_theory = parse_theory(self.theory_text) @@ -62,4 +63,4 @@ def test_prolog(self): 'Move top disk from left to right\n', 'yes: move(3, left, right, center)' ] - ) \ No newline at end of file + ) From e512d7362307eb35d0f3c9f9a1c50820dc63e34d Mon Sep 17 00:00:00 2001 From: Luca Deluigi Date: Fri, 13 Oct 2023 12:37:19 +0200 Subject: [PATCH 136/154] Fix test --- test/solve/prolog/test_prolog_parsing.py | 5 ++--- tuprolog/solve/flags/_adapters.py | 3 --- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/test/solve/prolog/test_prolog_parsing.py b/test/solve/prolog/test_prolog_parsing.py index 6b68310..8d770e3 100644 --- a/test/solve/prolog/test_prolog_parsing.py +++ b/test/solve/prolog/test_prolog_parsing.py @@ -2,7 +2,7 @@ from tuprolog.core import struct, atom, integer from tuprolog.theory.parsing import parse_theory from tuprolog.solve.prolog import prolog_solver -from tuprolog.solve.flags import DEFAULT_FLAG_STORE, LastCallOptimization +from tuprolog.solve.flags import DEFAULT_FLAG_STORE, LastCallOptimization, TrackVariables from tuprolog.solve.channel import output_channel @@ -38,10 +38,9 @@ def print_output(self, message): else: self.prints[-1] += message - @unittest.skip("TODO: fix this test") def test_prolog(self): logic_theory = parse_theory(self.theory_text) - flags = DEFAULT_FLAG_STORE.set(LastCallOptimization, LastCallOptimization.OFF) + flags = DEFAULT_FLAG_STORE.set(TrackVariables, TrackVariables.ON) solver = prolog_solver( static_kb=logic_theory, flags=flags, diff --git a/tuprolog/solve/flags/_adapters.py b/tuprolog/solve/flags/_adapters.py index 0194f54..84cc63c 100644 --- a/tuprolog/solve/flags/_adapters.py +++ b/tuprolog/solve/flags/_adapters.py @@ -14,9 +14,6 @@ def __len__(self): def __getitem__(self, notableFlag): return self.get(notableFlag) - def __setitem__(self, notableFlagName, notableFlag): - self.set(notableFlagName, notableFlag) - def __add__(self, other): return self.plus(other) From 3eddbec7f446f473ae2f35ca9e413a8852b65c74 Mon Sep 17 00:00:00 2001 From: Luca Deluigi Date: Fri, 13 Oct 2023 14:12:57 +0200 Subject: [PATCH 137/154] Fix flake --- test/solve/prolog/test_prolog_parsing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/solve/prolog/test_prolog_parsing.py b/test/solve/prolog/test_prolog_parsing.py index 8d770e3..6665a1c 100644 --- a/test/solve/prolog/test_prolog_parsing.py +++ b/test/solve/prolog/test_prolog_parsing.py @@ -2,7 +2,7 @@ from tuprolog.core import struct, atom, integer from tuprolog.theory.parsing import parse_theory from tuprolog.solve.prolog import prolog_solver -from tuprolog.solve.flags import DEFAULT_FLAG_STORE, LastCallOptimization, TrackVariables +from tuprolog.solve.flags import DEFAULT_FLAG_STORE, TrackVariables from tuprolog.solve.channel import output_channel From 60d8252dc84ea0b46ee584c96b00855b4b78a7a1 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Sat, 14 Oct 2023 02:33:04 +0200 Subject: [PATCH 138/154] Implement prolog and problog REPL with additional features --- README.md | 4 +- tuprolog/repl/__init__.py | 1 + tuprolog/repl/_definitions.py | 87 +++++++++++++++++++++++++++++++++++ tuprolog/repl/problog.py | 6 +++ tuprolog/repl/prolog.py | 6 +++ 5 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 tuprolog/repl/__init__.py create mode 100644 tuprolog/repl/_definitions.py create mode 100644 tuprolog/repl/problog.py create mode 100644 tuprolog/repl/prolog.py diff --git a/README.md b/README.md index 095b6c6..b1a082f 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,9 @@ other aimed at (de)serialising terms theories, namely `tuprolog.theory.serializ ### Use 2PPy as an interactive REPL 1. Python shell mode: `python -m tuprolog` -1. Logic solver [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop): *WIP* +1. Logic solver [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop): + 1. `python -m tuprolog.repl.prolog` for Prolog + 1. `python -m tuprolog.repl.problog` for ProbLog ## How to contribute to 2PPy diff --git a/tuprolog/repl/__init__.py b/tuprolog/repl/__init__.py new file mode 100644 index 0000000..47c7575 --- /dev/null +++ b/tuprolog/repl/__init__.py @@ -0,0 +1 @@ +from ._definitions import * diff --git a/tuprolog/repl/_definitions.py b/tuprolog/repl/_definitions.py new file mode 100644 index 0000000..47107ca --- /dev/null +++ b/tuprolog/repl/_definitions.py @@ -0,0 +1,87 @@ +from cmd import Cmd +from typing import IO +from tuprolog.core.parsing import TermParser, ParseException +from tuprolog.theory.parsing import ClausesParser +from tuprolog.solve import solution_formatter, TermFormatter +from tuprolog.solve import Solver + + +class PrologREPL(Cmd): + use_rawinput = False + + def __init__(self, + solver: Solver, + name: str, + completekey: str = "tab", + stdin: IO[str] | None = None, + stdout: IO[str] | None = None): + super().__init__(completekey, stdin, stdout) + self.intro = f""" +Welcome to the {name} REPL. + Usage + Assert a clause by typing it in. + Query the theory by typing ?- followed by a query. + Type ":help" for more information. + Type ":exit" to exit. +""" + self.solver = solver + self.name = name + self.clauses_parser = ClausesParser.withOperators(self.solver.operators) + self.query_parser = TermParser.withOperators(self.solver.operators) + self.solution_formatter = solution_formatter(TermFormatter.prettyExpressions(self.solver.operators)) + self.multi_line_command = "" + + @property + def prompt(self) -> str: + return "...>" if self.multi_line_command else f"{self.name}>" + + def emptyline(self) -> bool: + if self.multi_line_command: + return False + return super().emptyline() + + def precmd(self, line: str) -> str: + if line.startswith(":") or line.endswith("."): + command = self.multi_line_command + line + self.multi_line_command = "" + return command + self.multi_line_command += line + "\n" + return "" + + def do_exit(self, arg: str) -> bool: + """Exit the REPL.""" + return True + + def parseline(self, line: str) -> tuple[str | None, str | None, str]: + line = line.strip() + if line.startswith(":"): + return super().parseline(line[1:]) + if line.startswith("?-"): + return "query", line[2:].strip(), line + return "assert", line, line + + def do_query(self, arg: str) -> bool: + """Query the theory.""" + try: + query = self.query_parser.parse_struct(arg) + solutions = self.solver.solve(query) + for solution in solutions: + formatted = str(self.solution_formatter.format(solution)) + self.stdout.write(formatted) + self.stdout.write("\n") + except ParseException as e: + self.on_parsing_error(e) + return False + + def do_assert(self, arg: str) -> bool: + """Asserts a clause, appending to the theory.""" + try: + clauses = self.clauses_parser.parseClauses(arg) + for clause in clauses: + self.solver.assertZ(clause) + except ParseException as e: + self.on_parsing_error(e) + return False + + def on_parsing_error(self, err: ParseException) -> None: + self.stdout.write(f"Error: {err.message}\n".replace("''", "end of input")) diff --git a/tuprolog/repl/problog.py b/tuprolog/repl/problog.py new file mode 100644 index 0000000..ca41e03 --- /dev/null +++ b/tuprolog/repl/problog.py @@ -0,0 +1,6 @@ +from tuprolog.repl import PrologREPL +from tuprolog.solve.problog import problog_solver + + +if __name__ == '__main__': + PrologREPL(solver=problog_solver(mutable=True), name="problog").cmdloop() diff --git a/tuprolog/repl/prolog.py b/tuprolog/repl/prolog.py new file mode 100644 index 0000000..b6d81ed --- /dev/null +++ b/tuprolog/repl/prolog.py @@ -0,0 +1,6 @@ +from tuprolog.repl import PrologREPL +from tuprolog.solve.prolog import prolog_solver + + +if __name__ == '__main__': + PrologREPL(solver=prolog_solver(mutable=True), name="prolog").cmdloop() From 3d270e2b14ea040764a471d13a76401f6bef05c8 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Sat, 14 Oct 2023 10:23:25 +0200 Subject: [PATCH 139/154] Fix repl bugs --- tuprolog/repl/_definitions.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tuprolog/repl/_definitions.py b/tuprolog/repl/_definitions.py index 47107ca..f12ff5f 100644 --- a/tuprolog/repl/_definitions.py +++ b/tuprolog/repl/_definitions.py @@ -17,11 +17,14 @@ def __init__(self, stdout: IO[str] | None = None): super().__init__(completekey, stdin, stdout) self.intro = f""" -Welcome to the {name} REPL. +Welcome to the {name.title()} REPL. Usage Assert a clause by typing it in. Query the theory by typing ?- followed by a query. - Type ":help" for more information. + Clauses and queries must end with a period, otherwise they will be + considered incomplete and you will be prompted for more input. + Type ":help" for more information, including the list of available + commands that can be used by prefixing a colon ":". Type ":exit" to exit. """ self.solver = solver @@ -41,7 +44,9 @@ def emptyline(self) -> bool: return super().emptyline() def precmd(self, line: str) -> str: - if line.startswith(":") or line.endswith("."): + if line.startswith(":"): + return line + if line.endswith("."): command = self.multi_line_command + line self.multi_line_command = "" return command From 8418fcd93fd9eb5584ffc8def34e2c1dd75b85f0 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Sat, 14 Oct 2023 22:43:35 +0200 Subject: [PATCH 140/154] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b1a082f..c3a4168 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Experimental porting of [2P-Kt](https://github.com/tuProlog/2p-kt) on Python, vi Object-oriented and modular ecosystem for symbolic AI and logic programming, currently featuring: -* a command-line interface, in the form of a REPL, invoked by running `python -m tuprolog` +* a command-line interface, in the form of a REPL, invoked by running `python -m tuprolog` (for a python interpreter) or `python -m tuprolog.repl.prolog` (for a Prolog theory interpreter and solver) * a module for logic terms and clauses representation, namely `tuprolog.core` From 0f870d44971cb38c03104991e73cde22b27149c1 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Sun, 15 Oct 2023 18:17:11 +0200 Subject: [PATCH 141/154] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c3a4168..d5e8a0f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Experimental porting of [2P-Kt](https://github.com/tuProlog/2p-kt) on Python, vi Object-oriented and modular ecosystem for symbolic AI and logic programming, currently featuring: -* a command-line interface, in the form of a REPL, invoked by running `python -m tuprolog` (for a python interpreter) or `python -m tuprolog.repl.prolog` (for a Prolog theory interpreter and solver) +* [a command-line interface, in the form of a REPL](#use-2ppy-as-an-interactive-repl) * a module for logic terms and clauses representation, namely `tuprolog.core` From 0f3d62a6e41f8b8ab3aa16e0da36106cf4a52054 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Oct 2023 01:10:57 +0000 Subject: [PATCH 142/154] Bump it.unibo.tuprolog:solve-problog-jvm from 0.31.15 to 0.31.16 Bumps [it.unibo.tuprolog:solve-problog-jvm](https://github.com/tuProlog/2p-kt) from 0.31.15 to 0.31.16. - [Release notes](https://github.com/tuProlog/2p-kt/releases) - [Changelog](https://github.com/tuProlog/2p-kt/blob/master/CHANGELOG.md) - [Commits](https://github.com/tuProlog/2p-kt/compare/0.31.15...0.31.16) --- updated-dependencies: - dependency-name: it.unibo.tuprolog:solve-problog-jvm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a70e6c1..7a30b16 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ it.unibo.tuprolog solve-problog-jvm - 0.31.15 + 0.31.16 From 798e9b9dfb56438f70737a5c15debdd09af6ea42 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Oct 2023 01:11:01 +0000 Subject: [PATCH 143/154] Bump it.unibo.tuprolog:repl-jvm from 0.31.15 to 0.31.16 Bumps [it.unibo.tuprolog:repl-jvm](https://github.com/tuProlog/2p-kt) from 0.31.15 to 0.31.16. - [Release notes](https://github.com/tuProlog/2p-kt/releases) - [Changelog](https://github.com/tuProlog/2p-kt/blob/master/CHANGELOG.md) - [Commits](https://github.com/tuProlog/2p-kt/compare/0.31.15...0.31.16) --- updated-dependencies: - dependency-name: it.unibo.tuprolog:repl-jvm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a70e6c1..27b4270 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ it.unibo.tuprolog repl-jvm - 0.31.15 + 0.31.16 it.unibo.tuprolog From 5a093a97c5864eb7d22e7ddb9b74b23014b8ff97 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 16 Oct 2023 11:21:15 +0200 Subject: [PATCH 144/154] Fix and improve docs --- README.md | 34 +++++++++++++++------------------- pyproject.toml | 3 ++- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index d5e8a0f..4ce08d8 100644 --- a/README.md +++ b/README.md @@ -16,16 +16,12 @@ Object-oriented and modular ecosystem for symbolic AI and logic programming, cur * a module for in-memory indexing and storing logic theories, as well as other sorts of collections of logic clauses, namely `tuprolog.theory` -* a module providing generic API for resolution of logic queries, namely `tuprolog.solve`, currently implementing a Prolog solver +* a module providing generic API for resolution of logic queries, namely `tuprolog.solve` + * a module that implements deterministic logic programming and solving, namely `tuprolog.solve.prolog` + * a module that implements probabilistic logic programming and solving, namely `tuprolog.solve.problog` * two parsing modules: one aimed at parsing terms, namely `tuprolog.core.parsing`, and the other aimed at parsing theories, namely `tuprolog.theory.parsing` -* two serialisation-related modules: one aimed at (de)serialising terms and clauses, namely `tuprolog.core.serialize`, and the -other aimed at (de)serialising terms theories, namely `tuprolog.theory.serialize` - -* a module that implements probabilistic logic programming and solving, namely `tuprolog.solve.problog` - - ## How to use 2ppy ### Installing 2ppy @@ -33,11 +29,11 @@ other aimed at (de)serialising terms theories, namely `tuprolog.theory.serializ 1. Install Python 3 (look into the [`pyproject.toml`](pyproject.toml) to know the exact versions supported) * If your system has 64-bit processor, install the Python 3 64-bit distribution, and viceversa - * Ensure PIP works fine + * Ensure `pip` works fine * It's suggested to use a [virtual environment](https://docs.python.org/3/library/venv.html) to install the dependencies locally * It's suggested to use [Pyenv](https://github.com/pyenv/pyenv) to easily handle multiple Python versions on the same machine -1. If you have installed some prior development version of 2PPy (e.g. `tuppy` or `tuprolog`), uninstall them via +1. If you have installed some prior development version of 2PPy (e.g. `tuppy` and/or `tuprolog`), uninstall them via ```bash pip uninstall tuppy tuprolog ``` @@ -48,45 +44,45 @@ other aimed at (de)serialising terms theories, namely `tuprolog.theory.serializ ``` 1. Install 2PPy from Pypi by running: ```bash - pip install 2ppy + pip install tuprolog ``` On __Mac OS__ this may not work as expected. Consider running the following command instead: ```bash - python3 -m pip install 2ppy + python3 -m pip install tuprolog ``` 1. *Note #1 for the expert users:* 2ppy downloads its own [Java Virtual Machine](https://en.wikipedia.org/wiki/Java_virtual_machine) in order to call Java bytecode from python. If you install the package with sdist, it's downloaded during install. If you use the binary wheels packaging, it's downloaded on first import of the `tuprolog` package. 2. *Note #2 for the expert users:* The JVM version can be chosen by setting the `JAVA_VERSION` environment variable before downloading the JVM for the first time. -### Use 2ppy as a library +### Use 2ppy as a Python library 1. Import `tuprolog.*` modules in your Python scripts 1. Use the Pythonic API to write, parse or solve your logic programs. You can find some examples in the [api tests folder](test/api). ### Use 2PPy as an interactive REPL -1. Python shell mode: `python -m tuprolog` +1. Python shell mode: run `python -m tuprolog` 1. Logic solver [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop): - 1. `python -m tuprolog.repl.prolog` for Prolog - 1. `python -m tuprolog.repl.problog` for ProbLog + 1. run `python -m tuprolog.repl.prolog` for Prolog + 1. run `python -m tuprolog.repl.problog` for ProbLog ## How to contribute to 2PPy 1. Install dependencies - 1. Restore Python dev dependencies via PIP, by running: + 1. Restore Python dev dependencies via `pip`, by running: ```bash pip install -r requirements.txt ``` On __Mac OS__ this may not work as expected. Consider running the following command instead: ```bash - python3 -m pip -r requirements.txt + python3 -m pip install -r requirements.txt ``` - 1. Install [maven](https://maven.apache.org/install.html) and make sure that the `mvn` command is available in your `PATH` + 1. Install [maven](https://maven.apache.org/install.html) and make sure that the `mvn` command is available by adding Maven to your `PATH`. Maven is used to download java dependencies from the [Maven Central Repository for tuProlog](https://mvnrepository.com/artifact/it.unibo.tuprolog). 1. Write the code inside `tuprolog` and the unit tests inside `test` 1. Execute tests with `python -m pytest -p no:faulthandler` 1. Build the package with `python -m build` -1. Install the package locally with `python setup.py install` +1. Install the recently built package locally using wheels with `pip install dist/2ppy-$(python -m setuptools_git_versioning)-*.whl --force-reinstall` 1. Optionally, print the package version, computed from git tags with `python -m setuptools_git_versioning` ### Adopted Git flow diff --git a/pyproject.toml b/pyproject.toml index b13b2c8..17ed202 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,10 +10,11 @@ dynamic = ["version"] name = "2ppy" authors = [ { name="Giovanni Ciatto", email="giovanni.ciatto@unibo.it" }, + { name="Luca Deluigi", email="luca.deluigi5@unibo.it" }, ] description = "Python-based implementation of tuProlog -- the open ecosystem for symbolic AI --, based on 2P-Kt" readme = "README.md" -requires-python = ">=3.9, <4" +requires-python = ">=3.9, <3.12" classifiers=[ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", From 02f66b688fcf52db9691727a84b6c2f231d32c05 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 16 Oct 2023 15:57:59 +0200 Subject: [PATCH 145/154] Fix api and write agent test --- test/solve/prolog/test_thermostat_agent.py | 104 +++++++++++++++++++++ test/solve/prolog/thermostat.pl | 32 +++++++ tuprolog/jvmutils.py | 2 +- tuprolog/solve/library/__init__.py | 1 + tuprolog/solve/library/_adapters.py | 20 ++++ tuprolog/solve/library/_api.py | 9 +- tuprolog/solve/primitive/__init__.py | 1 + tuprolog/solve/primitive/_adapters.py | 14 +++ tuprolog/solve/primitive/_api.py | 2 +- tuprolog/theory/_adapters.py | 24 ----- 10 files changed, 179 insertions(+), 30 deletions(-) create mode 100644 test/solve/prolog/test_thermostat_agent.py create mode 100644 test/solve/prolog/thermostat.pl create mode 100644 tuprolog/solve/library/_adapters.py create mode 100644 tuprolog/solve/primitive/_adapters.py diff --git a/test/solve/prolog/test_thermostat_agent.py b/test/solve/prolog/test_thermostat_agent.py new file mode 100644 index 0000000..1bfcdd5 --- /dev/null +++ b/test/solve/prolog/test_thermostat_agent.py @@ -0,0 +1,104 @@ +import unittest +from typing import Iterable +from pathlib import Path +from tuprolog.core import atom, integer +from tuprolog.unify import mgu +from tuprolog.theory.parsing import parse_theory +from tuprolog.solve import signature +from tuprolog.solve.library import library, Library +from tuprolog.solve.primitive import primitive, Primitive, SolveRequest, SolveResponse, ensuring_argument_is_variable, ensuring_all_arguments_are_instantiated, ensuring_argument_is_atom +from tuprolog.solve.flags import TrackVariables +from tuprolog.solve.channel import output_channel +from tuprolog.solve.prolog import PROLOG_SOLVER_FACTORY + + +class ThermostatAgent: + def __init__(self, name: str, cold_threshold: int, hot_threshold: int, initial_temperature: int): + self.name = name + self.cold_threshold = cold_threshold + self.hot_threshold = hot_threshold + self.initial_temperature = initial_temperature + self._temperature = initial_temperature + + @property + def temperature(self) -> int: + return self._temperature + + def get_temp(self, request: SolveRequest) -> Iterable[SolveResponse]: + ensuring_argument_is_variable(request, 0) + sub = mgu(request.arguments[0], integer(self.temperature)) + return [request.reply_with(sub)] + + def push(self, request: SolveRequest) -> SolveResponse: + ensuring_all_arguments_are_instantiated(request) + ensuring_argument_is_atom(request, 0) + arg = request.arguments[0].cast_to_atom().value + if arg == "hot": + self._temperature += 1 + elif arg == "cold": + self._temperature -= 1 + else: + return request.reply_fail() + return [request.reply_success()] + + @property + def library(self) -> Library: + get_temp = primitive(self.get_temp) + push = primitive(self.push) + return library( + alias="libs.agency.thermostat", + primitives={ + signature("get_temp", arity=1): get_temp, + signature("push", arity=1): push + } + ) + + def program(self) -> str: + with open(Path(__file__).parent / "thermostat.pl", "r") as f: + return f.read() \ + .replace("__COLD_THRESHOLD__", str(self.cold_threshold)) \ + .replace("__HOT_THRESHOLD__", str(self.hot_threshold)) + + +class ThermostatAgentTest(unittest.TestCase): + def setUp(self) -> None: + self.thermostat_agent = ThermostatAgent("thermostat", 20, 24, 15) + self.prints: list[str] = [] + + def print_output(self, message): + message = str(message) + if len(self.prints) == 0: + self.prints.append(message) + elif self.prints[-1].endswith('\n'): + self.prints.append(message) + else: + self.prints[-1] += message + + def test_program(self): + theory = parse_theory(self.thermostat_agent.program()) + solver_builder = PROLOG_SOLVER_FACTORY.new_builder() \ + .static_kb(theory) \ + .flag(TrackVariables, TrackVariables.ON) \ + .standard_output(output_channel(self.print_output)) + solver_builder = solver_builder.runtime(solver_builder.get_runtime() + self.thermostat_agent.library.to_runtime()) + solver = solver_builder.build() + solution = solver.solve_once(atom("start")) + self.assertTrue(solution.is_yes) + self.assertSequenceEqual( + self.prints, + [ + "Temperature is 15.\n", + "Pushing hot air.\n", + "Temperature is 16.\n", + "Pushing hot air.\n", + "Temperature is 17.\n", + "Pushing hot air.\n", + "Temperature is 18.\n", + "Pushing hot air.\n", + "Temperature is 19.\n", + "Pushing hot air.\n", + "Temperature is 20.\n", + "Pushing hot air.\n", + "Temperature is 21.\n", + "I'm done.\n"] + ) diff --git a/test/solve/prolog/thermostat.pl b/test/solve/prolog/thermostat.pl new file mode 100644 index 0000000..8b954ed --- /dev/null +++ b/test/solve/prolog/thermostat.pl @@ -0,0 +1,32 @@ +:- dynamic(done/1). + +warm_range(__COLD_THRESHOLD__, __HOT_THRESHOLD__). +done(no). + +start :- + between(1, 20, _), + sleep(100 /* ms */), % just to slow down the execution + warm_range(Min, Max), + keep_temperature(Min, Max), + done(yes). + +keep_temperature(Min, Max) :- + check_temperature(T), + handle_temperature(T, Min, Max). + +check_temperature(T) :- + get_temp(T), + write("Temperature is "), write(T), write('.'), nl. + +handle_temperature(T, Min, _) :- T =< Min, !, + push(hot), + write("Pushing hot air."), nl. + +handle_temperature(T, _, Max) :- T >= Max, !, + push(cold), + write("Pushing cold air."), nl. + +handle_temperature(_, _, _) :- + retract(done(_)), !, + assert(done(yes)), + write("I'm done."), nl. diff --git a/tuprolog/jvmutils.py b/tuprolog/jvmutils.py index 85f86f0..a88b7b1 100644 --- a/tuprolog/jvmutils.py +++ b/tuprolog/jvmutils.py @@ -165,7 +165,7 @@ def __iter__(self): def ksequence(iterable: PyIterable) -> Sequence: - return SequencesKt.asSequence(jiterable(iterable)) + return SequencesKt.asSequence(jiterable(iterable).iterator()) @JConversion("kotlin.sequences.Sequence", instanceof=PyIterable, excludes=str) diff --git a/tuprolog/solve/library/__init__.py b/tuprolog/solve/library/__init__.py index e29704a..5cc9400 100644 --- a/tuprolog/solve/library/__init__.py +++ b/tuprolog/solve/library/__init__.py @@ -1,2 +1,3 @@ +import tuprolog.solve.library._adapters as _ from ._definititions import * from ._api import * diff --git a/tuprolog/solve/library/_adapters.py b/tuprolog/solve/library/_adapters.py new file mode 100644 index 0000000..6288935 --- /dev/null +++ b/tuprolog/solve/library/_adapters.py @@ -0,0 +1,20 @@ +from jpype import JImplementationFor +from._definititions import Runtime + + +@JImplementationFor("it.unibo.tuprolog.solve.library.Library") +class _KtLibrary: + def __jclass_init__(self): + pass + + def to_runtime(self): + return Runtime.of(self) + + +@JImplementationFor("it.unibo.tuprolog.solve.library.Runtime") +class _KtRuntime: + def __jclass_init__(self): + pass + + def __add__(self, other): + return self.plus(other) diff --git a/tuprolog/solve/library/_api.py b/tuprolog/solve/library/_api.py index 6f5286d..8d2095d 100644 --- a/tuprolog/solve/library/_api.py +++ b/tuprolog/solve/library/_api.py @@ -1,7 +1,8 @@ from typing import Union, Mapping, Iterable from functools import reduce +from tuprolog.jvmutils import protect_iterable from tuprolog.core.operators import OperatorSet, operator_set -from tuprolog.theory import Theory, theory +from tuprolog.theory import Clause from tuprolog.solve import Signature from tuprolog.solve.primitive import Primitive from tuprolog.solve.function import LogicFunction @@ -11,14 +12,14 @@ def library( alias: str = None, primitives: Mapping[Signature, Primitive] = dict(), - theory: Theory = theory(), + clauses: Iterable[Clause] = [], operators: OperatorSet = operator_set(), functions: Mapping[Signature, LogicFunction] = dict(), ) -> Union[Library, Pluggable]: if alias is None: - return Library.of(primitives, theory.clauses, operators, functions) + return Library.of(primitives, clauses, operators, functions) else: - return Library.of(alias, primitives, theory.clauses, operators, functions) + return Library.of(alias, primitives, clauses, operators, functions) def aliased(alias: str, library: Library) -> Library: diff --git a/tuprolog/solve/primitive/__init__.py b/tuprolog/solve/primitive/__init__.py index 3272497..e41f046 100644 --- a/tuprolog/solve/primitive/__init__.py +++ b/tuprolog/solve/primitive/__init__.py @@ -1,2 +1,3 @@ +import tuprolog.solve.primitive._adapters as _ from ._definitions import * from ._api import * diff --git a/tuprolog/solve/primitive/_adapters.py b/tuprolog/solve/primitive/_adapters.py new file mode 100644 index 0000000..df00ec4 --- /dev/null +++ b/tuprolog/solve/primitive/_adapters.py @@ -0,0 +1,14 @@ +from jpype import JImplementationFor +from tuprolog.core import Substitution + + +@JImplementationFor("it.unibo.tuprolog.solve.primitive.Solve.Request") +class _KtSolveRequest: + def __jclass_init__(self): + pass + + def reply_with(self, substitution): + return self.replyWith(substitution, None) + + def reply_success(self): + return self.replySuccess(Substitution.empty(), None) diff --git a/tuprolog/solve/primitive/_api.py b/tuprolog/solve/primitive/_api.py index 9421dfe..142916a 100644 --- a/tuprolog/solve/primitive/_api.py +++ b/tuprolog/solve/primitive/_api.py @@ -85,7 +85,7 @@ def ensuring_argument_is_compound(request: SolveRequest, index: int) -> SolveReq def ensuring_argument_is_atom(request: SolveRequest, index: int) -> SolveRequest: - return PrimitiveWrapper.ensuringArgumentIsCompound(request, index) + return PrimitiveWrapper.ensuringArgumentIsAtom(request, index) def ensuring_argument_is_constant(request: SolveRequest, index: int) -> SolveRequest: diff --git a/tuprolog/theory/_adapters.py b/tuprolog/theory/_adapters.py index ec84a60..28b4a5c 100644 --- a/tuprolog/theory/_adapters.py +++ b/tuprolog/theory/_adapters.py @@ -11,30 +11,6 @@ class _KtTheory: def __jclass_init__(cls): Sized.register(cls) - @JOverride - def getClauses(self): - return protect_iterable(self.getClauses_()) - - @property - def clauses(self): - return self.getClauses() - - @JOverride - def getRules(self): - return protect_iterable(self.getRules_()) - - @property - def rules(self): - return self.getRules() - - @JOverride - def getDirectives(self): - return protect_iterable(self.getDirectives_()) - - @property - def directives(self): - return self.getDirectives() - def __len__(self): return self.getSize() From 0935022bdda1a19a783fea11d7ba255152726b9d Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 16 Oct 2023 21:32:39 +0200 Subject: [PATCH 146/154] Improve code by avoiding using the solver factory/builder --- test/solve/prolog/test_thermostat_agent.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/solve/prolog/test_thermostat_agent.py b/test/solve/prolog/test_thermostat_agent.py index 1bfcdd5..cd48bb9 100644 --- a/test/solve/prolog/test_thermostat_agent.py +++ b/test/solve/prolog/test_thermostat_agent.py @@ -5,11 +5,11 @@ from tuprolog.unify import mgu from tuprolog.theory.parsing import parse_theory from tuprolog.solve import signature -from tuprolog.solve.library import library, Library -from tuprolog.solve.primitive import primitive, Primitive, SolveRequest, SolveResponse, ensuring_argument_is_variable, ensuring_all_arguments_are_instantiated, ensuring_argument_is_atom -from tuprolog.solve.flags import TrackVariables +from tuprolog.solve.library import library, libraries, Library +from tuprolog.solve.primitive import primitive, SolveRequest, SolveResponse, ensuring_argument_is_variable, ensuring_all_arguments_are_instantiated, ensuring_argument_is_atom +from tuprolog.solve.flags import DEFAULT_FLAG_STORE, TrackVariables from tuprolog.solve.channel import output_channel -from tuprolog.solve.prolog import PROLOG_SOLVER_FACTORY +from tuprolog.solve.prolog import prolog_solver class ThermostatAgent: @@ -76,12 +76,12 @@ def print_output(self, message): def test_program(self): theory = parse_theory(self.thermostat_agent.program()) - solver_builder = PROLOG_SOLVER_FACTORY.new_builder() \ - .static_kb(theory) \ - .flag(TrackVariables, TrackVariables.ON) \ - .standard_output(output_channel(self.print_output)) - solver_builder = solver_builder.runtime(solver_builder.get_runtime() + self.thermostat_agent.library.to_runtime()) - solver = solver_builder.build() + solver = prolog_solver( + libraries=self.thermostat_agent.library, + flags=DEFAULT_FLAG_STORE.set(TrackVariables, TrackVariables.ON), + static_kb=theory, + std_out=output_channel(self.print_output) + ) solution = solver.solve_once(atom("start")) self.assertTrue(solution.is_yes) self.assertSequenceEqual( From 1916ef2ebccd83cab212e4b755297237a0584ae5 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Mon, 16 Oct 2023 21:34:15 +0200 Subject: [PATCH 147/154] Fix style issues --- test/solve/prolog/test_thermostat_agent.py | 31 +++++++++++----------- tuprolog/solve/library/_adapters.py | 2 +- tuprolog/solve/library/_api.py | 1 - tuprolog/theory/_adapters.py | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/test/solve/prolog/test_thermostat_agent.py b/test/solve/prolog/test_thermostat_agent.py index cd48bb9..e1647c3 100644 --- a/test/solve/prolog/test_thermostat_agent.py +++ b/test/solve/prolog/test_thermostat_agent.py @@ -5,8 +5,9 @@ from tuprolog.unify import mgu from tuprolog.theory.parsing import parse_theory from tuprolog.solve import signature -from tuprolog.solve.library import library, libraries, Library -from tuprolog.solve.primitive import primitive, SolveRequest, SolveResponse, ensuring_argument_is_variable, ensuring_all_arguments_are_instantiated, ensuring_argument_is_atom +from tuprolog.solve.library import library, Library +from tuprolog.solve.primitive import primitive, SolveRequest, SolveResponse, ensuring_argument_is_variable, \ + ensuring_all_arguments_are_instantiated, ensuring_argument_is_atom from tuprolog.solve.flags import DEFAULT_FLAG_STORE, TrackVariables from tuprolog.solve.channel import output_channel from tuprolog.solve.prolog import prolog_solver @@ -87,18 +88,18 @@ def test_program(self): self.assertSequenceEqual( self.prints, [ - "Temperature is 15.\n", - "Pushing hot air.\n", - "Temperature is 16.\n", - "Pushing hot air.\n", - "Temperature is 17.\n", - "Pushing hot air.\n", - "Temperature is 18.\n", - "Pushing hot air.\n", - "Temperature is 19.\n", - "Pushing hot air.\n", - "Temperature is 20.\n", - "Pushing hot air.\n", - "Temperature is 21.\n", + "Temperature is 15.\n", + "Pushing hot air.\n", + "Temperature is 16.\n", + "Pushing hot air.\n", + "Temperature is 17.\n", + "Pushing hot air.\n", + "Temperature is 18.\n", + "Pushing hot air.\n", + "Temperature is 19.\n", + "Pushing hot air.\n", + "Temperature is 20.\n", + "Pushing hot air.\n", + "Temperature is 21.\n", "I'm done.\n"] ) diff --git a/tuprolog/solve/library/_adapters.py b/tuprolog/solve/library/_adapters.py index 6288935..16bee21 100644 --- a/tuprolog/solve/library/_adapters.py +++ b/tuprolog/solve/library/_adapters.py @@ -1,5 +1,5 @@ from jpype import JImplementationFor -from._definititions import Runtime +from ._definititions import Runtime @JImplementationFor("it.unibo.tuprolog.solve.library.Library") diff --git a/tuprolog/solve/library/_api.py b/tuprolog/solve/library/_api.py index 8d2095d..fd94003 100644 --- a/tuprolog/solve/library/_api.py +++ b/tuprolog/solve/library/_api.py @@ -1,6 +1,5 @@ from typing import Union, Mapping, Iterable from functools import reduce -from tuprolog.jvmutils import protect_iterable from tuprolog.core.operators import OperatorSet, operator_set from tuprolog.theory import Clause from tuprolog.solve import Signature diff --git a/tuprolog/theory/_adapters.py b/tuprolog/theory/_adapters.py index 28b4a5c..2a8bfb0 100644 --- a/tuprolog/theory/_adapters.py +++ b/tuprolog/theory/_adapters.py @@ -2,7 +2,7 @@ from jpype import JImplementationFor, JOverride from tuprolog import logger from tuprolog.core import indicator as new_indicator -from tuprolog.jvmutils import jiterable, protect_iterable +from tuprolog.jvmutils import jiterable from tuprolog.pyutils import iterable_or_varargs From f829c8ee598e52a709b9681f67819cb7b34a4d40 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 18 Oct 2023 12:58:01 +0200 Subject: [PATCH 148/154] Update deploy step --- .github/workflows/ci.yml | 5 +++-- README.md | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1130e93..3235664 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -145,7 +145,7 @@ jobs: needs: [build, lint, install] concurrency: group: release - if: ${{ startsWith(github.ref, 'refs/tags/') && github.event_name == 'push' }} + if: startsWith(github.ref, 'refs/tags/') && github.event_name == 'push' steps: - name: Download Artifacts uses: actions/download-artifact@v3 @@ -167,6 +167,8 @@ jobs: concurrency: group: publish environment: test-pypi + permissions: + id-token: write steps: - name: Download Artifacts uses: actions/download-artifact@v3 @@ -175,5 +177,4 @@ jobs: - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: - password: ${{ secrets.TEST_PYPI_TOKEN }} repository-url: https://test.pypi.org/legacy/ diff --git a/README.md b/README.md index 4ce08d8..ab491a1 100644 --- a/README.md +++ b/README.md @@ -97,8 +97,8 @@ The Git Flow for 2ppy consists of the following: ```bash git checkout master git merge develop - git tag -a v0.1.0 -m "First release" - git push origin master --tags + git tag -a 0.1.0 -m "First release" + git push origin master --follow-tags ``` #### CI/CD From 38779712f45345e6efdda695e99dc9661096269c Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 18 Oct 2023 15:20:21 +0200 Subject: [PATCH 149/154] Clean code and use generators where possible --- test/solve/prolog/test_thermostat_agent.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/solve/prolog/test_thermostat_agent.py b/test/solve/prolog/test_thermostat_agent.py index e1647c3..6d14097 100644 --- a/test/solve/prolog/test_thermostat_agent.py +++ b/test/solve/prolog/test_thermostat_agent.py @@ -28,9 +28,9 @@ def temperature(self) -> int: def get_temp(self, request: SolveRequest) -> Iterable[SolveResponse]: ensuring_argument_is_variable(request, 0) sub = mgu(request.arguments[0], integer(self.temperature)) - return [request.reply_with(sub)] + yield request.reply_with(sub) - def push(self, request: SolveRequest) -> SolveResponse: + def push(self, request: SolveRequest) -> Iterable[SolveResponse]: ensuring_all_arguments_are_instantiated(request) ensuring_argument_is_atom(request, 0) arg = request.arguments[0].cast_to_atom().value @@ -39,8 +39,8 @@ def push(self, request: SolveRequest) -> SolveResponse: elif arg == "cold": self._temperature -= 1 else: - return request.reply_fail() - return [request.reply_success()] + yield request.reply_fail() + yield request.reply_success() @property def library(self) -> Library: From d9017703f845a37858eaa703a521607dfaee4182 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 18 Oct 2023 18:15:20 +0200 Subject: [PATCH 150/154] Move to jvm4py --- .github/workflows/ci.yml | 15 ++++-------- README.md | 3 +-- pyproject.toml | 4 ++-- requirements.txt | 1 - setup.py | 14 ----------- tuprolog/__init__.py | 8 ++----- tuprolog/libs/__init__.py | 2 +- tuprolog/libs/java.py | 50 +++++++++++++++++++-------------------- 8 files changed, 34 insertions(+), 63 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3235664..f6e59a3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,13 +22,11 @@ jobs: matrix: os: [ubuntu, windows, macos] python-version: ['3.9', '3.10', '3.11'] - java-version: ['11', '17'] include: - package: false - os: ubuntu python-version: '3.9' - java-version: '11' - package: true + package: true # only build package artifacts once fail-fast: false runs-on: ${{ matrix.os }}-latest outputs: @@ -43,10 +41,10 @@ jobs: with: python-version: ${{ matrix.python-version }} cache: pip - - name: Set up Maven with Java ${{ matrix.java-version }} + - name: Set up Maven with Java 17 uses: actions/setup-java@v3 with: - java-version: ${{ matrix.java-version }} + java-version: '17' distribution: 'adopt' architecture: 'x64' cache: maven @@ -54,8 +52,6 @@ jobs: run: | python -m pip install --upgrade pip build - name: Build - env: - JAVA_VERSION: ${{ matrix.java-version }} run: | python -m build --sdist --wheel - name: Install @@ -71,7 +67,7 @@ jobs: id: artifact if: ${{ matrix.package }} run: | - echo 'artifact-name=${{ env.project-name }}-${{ matrix.python-version }}-${{ matrix.os }}-java${{ matrix.java-version }}' >> "$GITHUB_OUTPUT" + echo 'artifact-name=${{ env.project-name }}-${{ matrix.python-version }}-${{ matrix.os }}' >> "$GITHUB_OUTPUT" VERSION=$(python -m setuptools_git_versioning) echo "version=$VERSION" >> "$GITHUB_OUTPUT" - name: Upload artifacts @@ -108,13 +104,10 @@ jobs: matrix: os: [ubuntu, windows, macos] python-version: ['3.9', '3.10', '3.11'] - java-version: ['11', '17'] install: ['wheel', 'sdist'] fail-fast: false runs-on: ${{ matrix.os }}-latest needs: [build] - env: - JAVA_VERSION: ${{ matrix.java-version }} steps: - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 diff --git a/README.md b/README.md index ab491a1..82eacea 100644 --- a/README.md +++ b/README.md @@ -51,8 +51,7 @@ Object-oriented and modular ecosystem for symbolic AI and logic programming, cur ```bash python3 -m pip install tuprolog ``` -1. *Note #1 for the expert users:* 2ppy downloads its own [Java Virtual Machine](https://en.wikipedia.org/wiki/Java_virtual_machine) in order to call Java bytecode from python. If you install the package with sdist, it's downloaded during install. If you use the binary wheels packaging, it's downloaded on first import of the `tuprolog` package. -2. *Note #2 for the expert users:* The JVM version can be chosen by setting the `JAVA_VERSION` environment variable before downloading the JVM for the first time. +1. *Note for the expert users:* 2ppy downloads its own [Java Virtual Machine](https://en.wikipedia.org/wiki/Java_virtual_machine) in order to call Java bytecode from python. If you install the package with sdist, it's downloaded during install. If you use the binary wheels packaging, it's downloaded on first import of the `tuprolog` package. ### Use 2ppy as a Python library diff --git a/pyproject.toml b/pyproject.toml index 17ed202..043f7da 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools>=61", "wheel", "setuptools-git-versioning<2", "install-jdk==1.1.0"] +requires = ["setuptools>=61", "wheel", "setuptools-git-versioning<2"] build-backend = "setuptools.build_meta" [tool.setuptools-git-versioning] @@ -33,7 +33,7 @@ license = {file = "LICENSE"} keywords = ["prolog", "symbolic ai", "ecosystem", "tuprolog", "2p", "python"] dependencies = [ "JPype1==1.4.1", - "install-jdk==1.1.0" + "jdk4py==17.0.7.0" ] [project.urls] diff --git a/requirements.txt b/requirements.txt index e023717..ad8501b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,3 @@ flake8==6.1.0 pytest==7.4.2 setuptools-git-versioning==1.13.5 -install-jdk==1.1.0 diff --git a/setup.py b/setup.py index 7e2db32..621d9ea 100644 --- a/setup.py +++ b/setup.py @@ -54,22 +54,8 @@ def run(self): super().run() -class InstallCommand(install): - def run(self): - install.run(self) - - def _post_install(): - spec = importlib.util.spec_from_file_location(PACKAGE_NAME, JAR_FOLDER / '__init__.py') - lib = importlib.util.module_from_spec(spec) - sys.modules[spec.name] = lib - spec.loader.exec_module(lib) - lib.install_java_if_missing() - _post_install() - - setup( cmdclass={ 'build_py': BuildPyCommand, - 'install': InstallCommand, } ) diff --git a/tuprolog/__init__.py b/tuprolog/__init__.py index 9b9022e..b2b52e7 100644 --- a/tuprolog/__init__.py +++ b/tuprolog/__init__.py @@ -1,18 +1,14 @@ import os import logging import jpype -from .libs import JAVA_HOME, CLASSPATH, install_java_if_missing - -# Override the JAVA_HOME environment variable to use the locally installed JDK -os.environ['JAVA_HOME'] = str(JAVA_HOME) +from .libs import CLASSPATH, find_jvm logger = logging.getLogger('tuprolog') jars = [str(j.resolve()) for j in CLASSPATH.glob('*.jar')] if not jpype.isJVMStarted(): - install_java_if_missing() - jpype.startJVM(classpath=jars) + jpype.startJVM(classpath=jars, jvmpath=str(find_jvm())) import jpype.imports # noqa: F401, E402 from it.unibo import tuprolog as _tuprolog # type: ignore # noqa: E402 diff --git a/tuprolog/libs/__init__.py b/tuprolog/libs/__init__.py index 5505c02..224546d 100644 --- a/tuprolog/libs/__init__.py +++ b/tuprolog/libs/__init__.py @@ -1 +1 @@ -from .java import JAVA_HOME, CLASSPATH, install_java_if_missing +from .java import JAVA_HOME, CLASSPATH, find_jvm diff --git a/tuprolog/libs/java.py b/tuprolog/libs/java.py index a5a4ded..c92cc65 100644 --- a/tuprolog/libs/java.py +++ b/tuprolog/libs/java.py @@ -1,33 +1,31 @@ -import os -import jdk -import shutil -import logging +import sys from pathlib import Path +from jdk4py import JAVA_HOME -JAVA_HOME = Path(__file__).parent / 'java' +CLASSPATH = Path(__file__).parent -CLASSPATH = Path(__file__).parent +def __jvm_lib_file_names(): + if sys.platform == "win32": + return {"jvm.dll"} + elif sys.platform == "darwin": + return {"libjli.dylib"} + else: + return {"libjvm.so"} + + +def __jvmlib(): + for name in __jvm_lib_file_names(): + for path in JAVA_HOME.glob(f"**/{name}"): + path.resolve() + if path.exists: + return path + return None -logger = logging.getLogger('tuprolog') - - -def install_java_if_missing() -> Path: - if JAVA_HOME.exists(): - return - java_version = os.getenv('JAVA_VERSION', '11') - destination_folder = str(CLASSPATH) - logger.info(f'Downloading Java {java_version} in {destination_folder}') - installation_path = Path( - jdk.install( - java_version, - jre=not java_version.startswith('16'), # Java 16 doesn't have a JRE - path=destination_folder - ) - ) - destination_folder = JAVA_HOME - logger.info(f'Installing Java {java_version} in {destination_folder}') - shutil.copytree(installation_path, destination_folder, dirs_exist_ok=True) - shutil.rmtree(installation_path, ignore_errors=True) +def find_jvm() -> Path: + jvm = __jvmlib() + if jvm is None: + raise FileNotFoundError("Could not find jvm executable.") + return jvm From 7e6f9a8d144020253205285c758948a63679cc0a Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 18 Oct 2023 18:16:31 +0200 Subject: [PATCH 151/154] Fix ci pattern --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f6e59a3..8860eee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,6 +4,7 @@ on: push: branches: - "*" + - "**" tags: - "*" pull_request: From 25df56c77e20aff3fe26b16b0c10db675afbb3e2 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 18 Oct 2023 18:18:20 +0200 Subject: [PATCH 152/154] Fix flake issues --- setup.py | 3 --- tuprolog/libs/java.py | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 621d9ea..ba62d15 100644 --- a/setup.py +++ b/setup.py @@ -1,11 +1,8 @@ import platform import subprocess -import sys -import importlib.util from pathlib import Path from setuptools import setup from setuptools.command.build_py import build_py -from setuptools.command.install import install PACKAGE_NAME = 'tuprolog' diff --git a/tuprolog/libs/java.py b/tuprolog/libs/java.py index c92cc65..f8bb945 100644 --- a/tuprolog/libs/java.py +++ b/tuprolog/libs/java.py @@ -15,7 +15,7 @@ def __jvm_lib_file_names(): return {"libjvm.so"} -def __jvmlib(): +def __jvmlib(): for name in __jvm_lib_file_names(): for path in JAVA_HOME.glob(f"**/{name}"): path.resolve() From 2d84ed91ad0edaaa1bb46a102fc5ea960a84ec59 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Wed, 18 Oct 2023 18:36:18 +0200 Subject: [PATCH 153/154] Document protect_iterable --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 82eacea..95a640f 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,9 @@ Object-oriented and modular ecosystem for symbolic AI and logic programming, cur 1. Import `tuprolog.*` modules in your Python scripts 1. Use the Pythonic API to write, parse or solve your logic programs. You can find some examples in the [api tests folder](test/api). +1. *Known issues*: + Some methods called on `tuprolog` types are forwarded to the underlying Java objects. This means that the return type of such methods is not always the expected one. For example, the `tuprolog.theory.Theory` class has a `getClauses` method that returns an anonymous object tha *should* implement `java.util.Iterable`. However, iterating such object from Python will result in an error. + In order to avoid this, wrap these anonymous non-iterable objects with `protect_iterable(object: Iterable) -> Iterable` from `tuprolog.jvmutils` before iterating them. This will return an iterable object that can be safely iterated from Python. ### Use 2PPy as an interactive REPL From 688eb6cd7b36a3b4d88e72c433764ea886cc8ed3 Mon Sep 17 00:00:00 2001 From: ldeluigi <44567586+ldeluigi@users.noreply.github.com> Date: Thu, 19 Oct 2023 12:53:12 +0000 Subject: [PATCH 154/154] Add coverage to CI --- .github/workflows/ci.yml | 13 ++++++++----- requirements.txt | 2 ++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8860eee..ad638bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,19 +51,22 @@ jobs: cache: maven - name: Install build tool run: | - python -m pip install --upgrade pip build + python -m pip install --upgrade pip + - name: Install CI dependencies + run: | + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Build run: | python -m build --sdist --wheel - name: Install run: | pip install dist/*.whl - - name: Install CI dependencies - run: | - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Test run: | - python -m pytest -p no:faulthandler + coverage run -m pytest -p no:faulthandler + - name: Coverage + run: | + coverage report -i -m - name: Prepare artifacts id: artifact if: ${{ matrix.package }} diff --git a/requirements.txt b/requirements.txt index ad8501b..0b62b7b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,6 @@ # CI & Test dependencies flake8==6.1.0 +build==1.0.3 pytest==7.4.2 +coverage==7.3.2 setuptools-git-versioning==1.13.5