Add configure() function to set up logging, tracebacks printing, plot styling, etc.
Closes #195 (closed).
This adds a configure
method to finesse
that configures the display of log messages depending on whether the user is running Finesse interactively or not. It also allows the user to configure the Finesse plotting, which internally calls init_plotting()
. I see this function as a Finesse equivalent of the Python standard library's logging.basicConfig()
which sets up sensible defaults depending on the environment.
There is also a new context manager to temporarily enable logging to stderr:
from finesse.script import parse
from finesse.utilities import logs
script = """
laser l1 P=1
space s1 l1.p1 m1.p1
mirror m1 R=0.99 T=0.01
"""
print("Parsing without printed log messages...")
print(parse(script))
print()
with logs(level="info"):
print("Parsing with printed log messages...")
print(parse(script))
This outputs:
Parsing without printed log messages...
Model(λ=1064 nm, untraced, unbuilt)
Parsing with printed log messages...
finesse.analysis.actions [ INFO]: Scanning parameters []
finesse.script.parser [ INFO]: No analysis specified; defaulting to 'noxaxis'.
Model(λ=1064 nm, untraced, unbuilt)
(This example is in playground/logging/log_contexts.py
.
Logging configuration is a little complex. If the user is running in an interactive way (IPython, Jupyter, Qtconsole, etc.), then logging is configured by default to log WARNING
messages or higher to stderr
(both are Python logging defaults) without any need to call configure()
. If the user subsequently calls configure()
within an interactive session, e.g. to change to a different log level, then this automatically configured logger gets changed. However, if the user has already configured logging themselves by the time they import finesse
, logging is not configured unless the user calls configure(log_level=...)
to indicate they explicitly want to set it up. Finally, if the user is running non-interactively, e.g. via the normal Python shell or command, then logging is not set up automatically at all and the user must call configure()
or some other means to set up logging.
There is a truth table in the docstring for configure()
, though for some reason I can't get this to display in the API docs because for some reason functions in the root package are not written into the docs (#196 (closed)):
============ ==================== ================= ======================= ================
Interactive? Log level specified? Existing handler? Add Finesse handler Add null handler
============ ==================== ================= ======================= ================
no no no no yes
no no yes no no
no yes no yes, user defined level no
no yes yes yes, user defined level no
yes no no yes, default level no
yes no yes yes, default level no
yes yes no yes, user defined level no
yes yes yes yes, user defined level no
There is also a new documentation page showing how to enable logging in various circumstances.
This MR also tweaks the config file hierarchy to no longer copy the "base" configuration to the user's config directory but instead keep it in the source directory. There seems to me to be no point to copy it at all, and this copying was being done on every Finesse run which adds an unnecessary file system operation (and slowdown). Now only a "barebone" user configuration is copied from src/finesse/usr.ini.dist
into the user's home config directory, and the "built-in" config stays in the installation location (which is probably better anyway, as this file should really be managed by the package manager and not be something left around in the user directory).