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.4.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.4.0
File Size Uploaded Provenance
2ppy-1.4.0.tar.gz 12.2 MB Without provenance Details

Built distribution (wheel)

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

Total release size: 24.5 MB

Release files / 2ppy-1.4.0.tar.gz

Download URL 2ppy-1.4.0.tar.gz
Size 12.2 MB
Tags Source
SHA-256 checksum
How to use checksums
0040b9bfeb4270ea48071ea1f2f682e464ffe4cbf17c2dd6329ad7158d792120
BLAKE2b-256 checksum
How to use checksums
d2fe253c4e489ad4ca4253173ba12391a5a59612dcb5efba8f3280e3d8e0f9a8
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.4.0-py3-none-any.whl

Download URL 2ppy-1.4.0-py3-none-any.whl
Size 12.3 MB
Tags Python 3
SHA-256 checksum
How to use checksums
38901858dc270a83eea7f650843c8bd388962a04767fb21841f3205c7a665ae2
BLAKE2b-256 checksum
How to use checksums
85005bf75c1bcc1dbb0e74ca57ab4c545d08a81a8d4f6c554e3391190fe2ef61
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.4.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.4.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