Imacropy
Imacropy is interactive macropy.
We provide some agile-development addons for MacroPy, namely:
-
imacropy.iconsole
, IPython extension. Use macros in the IPython REPL.
-
imacropy.console.MacroConsole
, a macro-enabled equivalent of code.InteractiveConsole
. Embed a REPL that supports macros.
-
macropy3
, a generic bootstrapper for macro-enabled Python programs. Use macros in your main program.
Changed in v0.2.0. Due to the addition of MacroConsole
, which is more deserving of the module name imacropy.console
, the IPython extension has been renamed to imacropy.iconsole
(note the second i
). Please update your IPython profile. This is a permanent rename, iconsole
will not be renamed again.
IPython extension
The extension allows to use macros in the IPython REPL. (Defining macros in the REPL is currently not supported.)
For example:
In [1]: from simplelet import macros, let
In [2]: let((x, 21))[2*x]
Out[2]: 42
A from-import of macros from a given module clears from the REPL session all current macros loaded from that module, and loads the latest definitions of only the specified macros from disk. This allows interactive testing when editing macros.
The most recent definition of any given macro remains alive until the next macro from-import from the same module, or until the IPython session is terminated.
Macro docstrings and source code can be viewed using ?
and ??
, as usual.
Added in v0.3.1. The line magic %macros
now prints a human-readable list of macros that are currently imported into the REPL session (or says that no macros are imported, if so).
Loading the extension
To load the extension once, %load_ext imacropy.iconsole
.
To autoload it when IPython starts, add the string "imacropy.iconsole"
to the list c.InteractiveShellApp.extensions
in your ipython_config.py
. To find the config file, ipython profile locate
.
When the extension loads, it imports macropy
into the REPL session. You can use this to debug whether it is loaded, if necessary.
Currently no startup banner is printed, because extension loading occurs after IPython has already printed its own banner. We cannot manually print a banner, because some tools (notably importmagic.el
for Emacs, included in Spacemacs) treat the situation as a fatal error in Python interpreter startup if anything is printed (and ipython3 --no-banner
is rather convenient to have as the python-shell, to run IPython in Emacs's inferior-shell mode).
MacroConsole
This is a derivative of, and drop-in replacement for, code.InteractiveConsole
, which allows you to embed a REPL that supports macros. The difference to macropy.core.console.MacroConsole
is that this one offers the same semantics as the IPython extension. We also offer the ?
and ??
syntax to view docstrings and source code.
from imacropy.console import MacroConsole
m = MacroConsole()
m.interact()
Now we're inside a macro-enabled REPL:
from unpythonic.syntax import macros, let
x = let[((a, 21)) in 2 * a]
assert x == 42
Just like in code.InteractiveConsole
, exiting the REPL (Ctrl+D) returns from the interact()
call.
Macro docstrings and source code can be viewed like in IPython:
let?
let??
If the information is available, these operations also print the filename and the starting line number of the definition of the queried object in that file.
The obj?
syntax is shorthand for imacropy.doc(obj)
, and obj??
is shorthand for imacropy.sourcecode(obj)
.
Note that just like in IPython, for some reason help(some_macro)
sees only the generic docstring of WrappedMacro
, not that of the actual macro stub object. So use the ?
syntax to view macro docstrings, as you would in IPython.
Added in v0.3.1. The literal command macros?
now prints a human-readable list of macros that are currently imported into the REPL session (or says that no macros are imported, if so). This shadows the obj?
docstring lookup syntax for the MacroPy special object macros
, but that's likely not needed. That can still be invoked manually, using imacropy.doc(macros)
.
Bootstrapper
The bootstrapper imports the specified file or module, pretending its __name__
is "__main__"
. This allows your main program to use macros.
For example, some_program.py
:
from simplelet import macros, let
def main():
x = let((y, 21))[2*y]
assert x == 42
print("All OK")
if __name__ == "__main__":
main()
Start it as:
macropy3 some_program.py
A relative path is ok, as long as it is under the current directory. Relative paths including ..
are not supported. We also support the -m module_name
variant:
macropy3 -m some_program
A dotted module path under the current directory is ok.
If you need to set other Python command-line options:
python3 <your options here> $(which macropy3) -m some_program
This way the rest of the options go to the Python interpreter itself, and the -m some_program
to the macropy3
bootstrapper.
Installation
From PyPI
Install as user:
pip install imacropy --user
Install as admin:
sudo pip install imacropy
From GitHub
As user:
git clone https://github.com/Technologicat/imacropy.git
cd imacropy
python setup.py install --user
As admin, change the last command to
sudo python setup.py install
Dependencies
MacroPy3.
License
BSD. Copyright 2019-2020 Juha Jeronen and University of Jyväskylä.