Skip to main content

2PPy (tuProlog in Python)

Experimental porting of 2P-Kt on Python, via JPype.

This is a work in progress.

Introduction

Object-oriented and modular ecosystem for symbolic AI and logic programming, currently featuring:

  • a command-line interface, in the form of a REPL

  • a module for logic terms and clauses representation, namely tuprolog.core

  • a module for logic unification, namely tuprolog.unify

  • a module for in-memory indexing and storing logic theories, namely tuprolog.theory

  • a module for other indexed collections of logic clauses (multi-sets and queues), namely tuprolog.collections

  • 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
    • a module exposing 2P-Kt's IO library (e.g. read/1, get_char/1, open/3), namely tuprolog.solve.libs
  • two parsing modules: one aimed at parsing terms, namely tuprolog.core.parsing, and the other aimed at parsing theories, namely tuprolog.theory.parsing

How to use 2ppy

Installing 2ppy

Install 2PPy from PyPI (Python 3.10 or later):

pip install 2ppy        # or: uv add 2ppy

The package ships 2P-Kt's JARs, and depends on jdk4py, which bundles a Java runtime: no separate Java installation is required. The JVM is started when tuprolog is first imported.

Use 2ppy as a Python library

  1. Import tuprolog.* modules in your Python scripts
  2. Use the Pythonic API to write, parse or solve your logic programs. You can find some examples in the tests folder.
  3. Query solvers the Pythonic way:
    from tuprolog.solve.prolog import prolog_solver
    from tuprolog.theory.parsing import parse_theory
    
    solver = prolog_solver(static_kb=parse_theory("parent(abe, homer). parent(homer, bart)."))
    for bindings in solver.query("parent(X, Y)"):  # errors are raised as Python exceptions
        print(bindings)  # {'X': 'abe', 'Y': 'homer'}, then {'X': 'homer', 'Y': 'bart'}
    solution = solver.solve_once("parent(abe, Who)")  # goals may be strings
    if solution:  # i.e. solution.is_yes
        print(solution["Who"])  # homer (a term), see also solution.bindings and solution.to_dict()
    
  4. Extend solvers with plain Python functions, whose arguments and results are converted: predicate makes a primitive from a function returning a boolean, or returning (or yielding) tuples of argument values, one per solution; function makes an arithmetic function.
    from tuprolog.solve.function import function
    from tuprolog.solve.library import library
    from tuprolog.solve.primitive import predicate
    
    lib = library(
        "my.lib",
        primitives={"upper/2": predicate(lambda s, _: [(s, s.upper())])},
        functions={"half/1": function(lambda x: x / 2)},
    )
    list(prolog_solver(libraries=lib).query("upper(abc, U), H is half(3)"))  # [{'U': 'ABC', 'H': 1.5}]
    
    Python exceptions raised by primitives become logic system_errors, which catch/3 can handle.
  5. Python values are converted where terms are expected (e.g. struct("f", "a", 1) is f(a, 1), see tuprolog.core.to_term), and back (see tuprolog.core.to_python). Methods without a Pythonic counterpart are forwarded to the underlying JVM objects, so they may return JVM types (e.g. java.lang.String).
  6. Python streams (io.IOBase, e.g. files, sys.stdin, io.StringIO, io.BytesIO) are accepted wherever 2P-Kt reads or writes: parsers (read_theory(open("kb.pl"))), solvers' channels (prolog_solver(std_in=io.StringIO("..."), std_out=buffer)), and JVM methods expecting streams (binary), readers or writers (text). Binary streams are UTF-8 encoded. By default, solvers read from and write on Python's current sys.stdin, sys.stdout and sys.stderr.
  7. 2P-Kt's exceptions are classified by the Python exceptions in tuprolog.errors, and by Python's built-in ones: e.g. parsing errors are ParsingErrors and ValueErrors, a logic type_error is a PrologTypeError and a TypeError, and every exception raised by 2P-Kt is a TuPrologError.

Use 2PPy as an interactive REPL

  1. Python shell mode: run python -m tuprolog
  2. Logic solver REPL:
    1. run python -m tuprolog.repl.prolog for Prolog
    2. run python -m tuprolog.repl.problog for ProbLog

How to contribute to 2PPy

The project follows template-python-project-uv. Requirements: uv and Apache Maven (mvn on the PATH), which downloads 2P-Kt's JARs from Maven Central, as declared in pom.xml.

uv sync                      # create the environment, with the development tools
uv run poe fetch-jars        # download the JARs into tuprolog/libs/ (needed before testing or building)
uv run poe test              # run the tests
uv run poe static-checks     # compileall, ruff format --check, ruff check, mypy (what CI runs)
uv run poe static-fixes      # ruff check --fix + ruff format
uv run poe coverage && uv run poe coverage-report
uv build                     # wheel and sdist in dist/ (JARs included)

Write the code inside tuprolog/ and the tests inside tests/. Contributor notes (layout, conventions) are in AGENTS.md. Optional local Git hooks: uv run poe install-hooks [HOOK...] (pre-commit, conventional-commits, no-ai-signature, pre-push).

Releases

Commits follow Conventional Commits: on every push to master, semantic-release derives the next version from them, publishes it on PyPI, and creates the corresponding GitHub Release. pyproject.toml is the only version source: never bump it by hand. The release workflow needs the PYPI_TOKEN and RELEASE_TOKEN repository secrets.

CI runs the static checks and the tests on Ubuntu, Windows and macOS, with Python 3.10 to 3.13. Dependencies are kept up to date by Renovate.

Metadata

Release files for 2ppy 1.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for 2ppy 1.3.0
File Size Uploaded Provenance
2ppy-1.3.0.tar.gz 12.2 MB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for 2ppy 1.3.0
File Interpreter ABI Platform
2ppy-1.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 24.5 MB

Release files / 2ppy-1.3.0.tar.gz

Download URL 2ppy-1.3.0.tar.gz
Size 12.2 MB
Tags Source
SHA-256 checksum
How to use checksums
4544d199a5f4c8db8f8297c38e03f7594018faa2a021a25c884f9bd355cb5028
BLAKE2b-256 checksum
How to use checksums
a0cd3c98a9e31d81e6eecc548c21849b885a54cf24c6e1d73f60e7d0bb245fdc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / 2ppy-1.3.0-py3-none-any.whl

Download URL 2ppy-1.3.0-py3-none-any.whl
Size 12.3 MB
Tags Python 3
SHA-256 checksum
How to use checksums
5cddfe92e2457277b74cb42406213645d37baf28d115bc03609773e6a31b78d2
BLAKE2b-256 checksum
How to use checksums
4b2af2ccb06d8563299eceb80fe6119307faacb37e9439257cdf047541949e63
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for 2ppy 1.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

1.3.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page