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)