Note
Go to the end to download the full example code
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)