https://macropy3.readthedocs.io/en/latest/overview.html says,
Note that this means you cannot use macros in a file that is run directly, as it will not be passed through the import hooks.
Sometimes I use Python for big projects, but sometimes I just need a one-page script and just want to import my macros and run it directly. It's a pain to have to write a new launcher to import it every time just so I can have macros.
Writing a macropy launcher aliased to replace python altogether would help some, but it messes up the if __name__ == '__main__': pattern I need to use sometimes. Then I'd have to remember to launch with normal python instead, but only if I didn't use macros...
Anyway, I think we can do better.
macros/__init__.py
import macropy.activate
from . import macros_in_main
macros/macros_in_main.py
import ast, importlib, inspect
from macropy.core.macros import ModuleExpansionContext, detect_macros
frame = inspect.currentframe()
while frame.f_globals["__name__"] != "__main__":
frame = frame.f_back
source = inspect.getsource(frame)
tree = ast.parse(source)
exec(
compile(
ast.Module(
ModuleExpansionContext(
tree,
source,
[
(importlib.import_module(mod), bind)
for mod, bind in (detect_macros(tree, "__main__"))
],
)
.expand_macros()
.body
),
"__main__",
"exec",
)
)
raise SystemExit
main.py
import macros
from macropy.case_classes import macros, enum
@enum
class Direction:
North, South, East, West
print(Direction(name="North")) # Direction.North
$ python main.py
Direction.North
This is just a proof of concept. I'm probably missing some edge cases and interactions, but it proves that it's at least possible to have syntactic macros, even in a file that is run "directly".
Maybe there's an easier way to do this, but I didn't see any kind of exec_with_macros() in the library.
Something like the above could perhaps replace the import macropy.activate to allow a script to be both imported and run on its own (the usual use case for the if __name__ == '__main__': construct).
https://macropy3.readthedocs.io/en/latest/overview.html says,
Sometimes I use Python for big projects, but sometimes I just need a one-page script and just want to import my macros and run it directly. It's a pain to have to write a new launcher to import it every time just so I can have macros.
Writing a
macropylauncher aliased to replacepythonaltogether would help some, but it messes up theif __name__ == '__main__':pattern I need to use sometimes. Then I'd have to remember to launch with normalpythoninstead, but only if I didn't use macros...Anyway, I think we can do better.
macros/__init__.pymacros/macros_in_main.pymain.pyThis is just a proof of concept. I'm probably missing some edge cases and interactions, but it proves that it's at least possible to have syntactic macros, even in a file that is run "directly".
Maybe there's an easier way to do this, but I didn't see any kind of
exec_with_macros()in the library.Something like the above could perhaps replace the
import macropy.activateto allow a script to be both imported and run on its own (the usual use case for theif __name__ == '__main__':construct).