Basic usage example.#

In what case to use#

This client might be useful if:

  • you have a machine with Isabelle installed

  • you have scripts for automatic generation of theory files in Python

  • you want to communicate with the server not using Scala and/or Standard ML

In what environment to use#

The client works well in scripts and in Jupyter notebooks. For the latter, one has to enable nested event loops first. Please refer to nest_asyncio documentation.

Starting Isabelle server#

First, we need to start an Isabelle server

from isabelle_client import start_isabelle_server

server_info, _ = start_isabelle_server(
    name="test", port=9999, log_file="server.log"
)

Warning

When using start_isabelle_server utility function in Python REPL or terminal IPython, shutting the server down within the same session is known to cause a runtime error on exit from the session. This behaviour is related to a well known issue.

We could also start the server outside this script and use its info (on Windows, this is done in Cygwin):

isabelle server

Interacting with Isabelle server#

Let’s create a client to our server

from isabelle_client import get_isabelle_client

isabelle = get_isabelle_client(server_info)

We will log all the messages from the server to a file

import logging

isabelle.logger = logging.getLogger()
isabelle.logger.setLevel(logging.INFO)
isabelle.logger.addHandler(logging.FileHandler("session.log"))

Isabelle client supports all the commands implemented in Isabelle server

from pprint import pprint

pprint(isabelle.help())
[IsabelleResponse(response_type='OK',
                  response_body='{"isabelle_id":"b5f3d1051b13","isabelle_name":"Isabelle2023"}',
                  response_length=None),
 IsabelleResponse(response_type='OK',
                  response_body='["cancel","echo","help","purge_theories","session_build","session_start","session_stop","shutdown","use_theories"]',
                  response_length=118)]

Let’s suppose we have a Example.thy theory file in our working directory which we, e.g. generated with another Python script

theory Example
imports Main
begin
lemma "\<forall> x. \<exists> y. x = y"
by auto
end

We can send this theory file to the server and get a response

pprint(isabelle.use_theories(theories=["Example"], master_dir="."))
[IsabelleResponse(response_type='OK',
                  response_body='{"isabelle_id":"b5f3d1051b13","isabelle_name":"Isabelle2023"}',
                  response_length=None),
 IsabelleResponse(response_type='OK',
                  response_body='{"task":"9ea417a7-81c2-4a70-a6ee-e7da5ff58af5"}',
                  response_length=None),
 IsabelleResponse(response_type='NOTE',
                  response_body='{"percentage":14,"task":"9ea417a7-81c2-4a70-a6ee-e7da5ff58af5","message":"theory '
                                'Draft.Example '
                                '14%","kind":"writeln","session":"","theory":"Draft.Example"}',
                  response_length=161),
 IsabelleResponse(response_type='NOTE',
                  response_body='{"percentage":42,"task":"9ea417a7-81c2-4a70-a6ee-e7da5ff58af5","message":"theory '
                                'Draft.Example '
                                '42%","kind":"writeln","session":"","theory":"Draft.Example"}',
                  response_length=161),
 IsabelleResponse(response_type='NOTE',
                  response_body='{"percentage":99,"task":"9ea417a7-81c2-4a70-a6ee-e7da5ff58af5","message":"theory '
                                'Draft.Example '
                                '99%","kind":"writeln","session":"","theory":"Draft.Example"}',
                  response_length=161),
 IsabelleResponse(response_type='NOTE',
                  response_body='{"percentage":100,"task":"9ea417a7-81c2-4a70-a6ee-e7da5ff58af5","message":"theory '
                                'Draft.Example '
                                '100%","kind":"writeln","session":"","theory":"Draft.Example"}',
                  response_length=163),
 IsabelleResponse(response_type='FINISHED',
                  response_body='{"ok":true,"errors":[],"nodes":[{"messages":[{"kind":"writeln","message":"theorem '
                                '\\\\<forall>x. \\\\<exists>y. x = '
                                'y","pos":{"line":5,"offset":59,"end_offset":61,"file":"Example.thy"}}],"exports":[],"status":{"percentage":100,"unprocessed":0,"running":0,"finished":7,"failed":0,"total":7,"consolidated":true,"canceled":false,"ok":true,"warned":0},"theory_name":"Draft.Example","node_name":"Example.thy"}],"task":"9ea417a7-81c2-4a70-a6ee-e7da5ff58af5"}',
                  response_length=458)]

or we can build a session document using ./ROOT file

session examples = HOL +
  options [document = pdf, document_output = "output"]
  theories
    Example
  document_files
    "root.tex"

and ./document/root.tex file

\documentclass{article}
\usepackage{isabelle,isabellesym}
\begin{document}
\input{session}
\end{document}
import json

pprint(
    json.loads(
        isabelle.session_build(dirs=["."], session="examples")[
            -1
        ].response_body
    )
)
{'ok': True,
 'return_code': 0,
 'sessions': [{'ok': True,
               'return_code': 0,
               'session': 'Pure',
               'timeout': False,
               'timing': {'cpu': 0, 'elapsed': 0, 'gc': 0}},
              {'ok': True,
               'return_code': 0,
               'session': 'HOL',
               'timeout': False,
               'timing': {'cpu': 0, 'elapsed': 0, 'gc': 0}},
              {'ok': True,
               'return_code': 0,
               'session': 'examples',
               'timeout': False,
               'timing': {'cpu': 14.567, 'elapsed': 9.41, 'gc': 0}}],
 'task': 'e36e45b8-6f6b-42a7-9c95-3873b2fd9b89'}

One can also issue a free-form command, e.g.

import asyncio

pprint(asyncio.run(isabelle.execute_command("echo 42", asynchronous=False)))
[IsabelleResponse(response_type='OK',
                  response_body='{"isabelle_id":"b5f3d1051b13","isabelle_name":"Isabelle2023"}',
                  response_length=None),
 IsabelleResponse(response_type='OK', response_body='42', response_length=None)]

Finally, we can shut the server down.

pprint(isabelle.shutdown())
[IsabelleResponse(response_type='OK',
                  response_body='{"isabelle_id":"b5f3d1051b13","isabelle_name":"Isabelle2023"}',
                  response_length=None),
 IsabelleResponse(response_type='OK', response_body='', response_length=None)]

Total running time of the script: (1 minutes 1.590 seconds)

Gallery generated by Sphinx-Gallery