Source code for pennylane.logging.configuration
# Copyright 2018-2023 Xanadu Quantum Technologies Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
This module contains support methods for configuring the logging functionality.
"""
import logging
import logging.config
import os
import platform
import subprocess
from importlib import import_module
from importlib.util import find_spec
from typing import Optional
has_toml = False
toml_libs = ["tomllib", "tomli", "tomlkit"]
for pkg in toml_libs:
spec = find_spec(pkg)
if spec:
tomllib = import_module(pkg)
has_toml = True
break
# Define absolute path to this file in source tree
_path = os.path.dirname(__file__)
# Define a more verbose log-level. Not currently controlled by internal log configurations.
TRACE = logging.DEBUG // 2
def _add_trace_level():
"Wrapper to define custom TRACE level for PennyLane logging"
def trace(self, message, *args, **kws):
"""Enable a more verbose mode than DEBUG. Used to enable inspection of function definitions in log messages."""
# Due to limitations in how the logging module exposes support for custom levels,
# accessing the private method `_log` has no alternative.
# pylint: disable=protected-access
self._log(TRACE, message, args, **kws)
logging.addLevelName(TRACE, "TRACE")
logging.TRACE = TRACE
lc = logging.getLoggerClass()
lc.trace = trace
def _configure_logging(config_file: str, config_override: Optional[dict] = None):
"""
This method allows custom logging configuration throughout PennyLane.
All configurations are read through the ``log_config.toml`` file, with additional custom options provided through the ``config_override`` dictionary.
Args:
config_file (str): The path to a given log configuration file, parsed as TOML and adhering to the ``logging.config.dictConfig`` end-point.
config_override (Optional[dict]): A dictionary with keys-values that override the default configuration options in the given ``config_file`` TOML.
"""
if not has_toml:
raise ImportError(
"A TOML parser is required to enable PennyLane logging defaults. "
"We support any of the following TOML parsers: [tomli, tomlkit, tomllib] "
"You can install either tomli via `pip install tomli`, "
"tomlkit via `pip install tomlkit`, or use Python 3.11 "
"or above which natively offers the tomllib library."
)
with open(os.path.join(_path, config_file), "rb") as f:
pl_config = tomllib.load(f)
if not config_override:
logging.config.dictConfig(pl_config)
else:
logging.config.dictConfig({**pl_config, **config_override})
[docs]def enable_logging(config_file: str = "log_config.toml"):
"""
This method allows to selectively enable logging throughout PennyLane, following the configuration options defined in the ``log_config.toml`` file.
Enabling logging through this method will override any externally defined logging configurations.
Args:
config_file (str): The path to a given log configuration file, parsed as TOML and adhering to the ``logging.config.dictConfig`` end-point. The default argument uses the PennyLane ecosystem log-file configuration, located at the directory returned from :func:`pennylane.logging.config_path`.
**Example**
>>> qml.logging.enable_logging()
"""
_add_trace_level()
_configure_logging(config_file)
[docs]def config_path():
"""
This method returns the full absolute path to the the ``log_config.toml`` configuration file.
Returns:
str: System path to the ``log_config.toml`` file.
**Example**
>>> config_path()
/home/user/pyenv/lib/python3.10/site-packages/pennylane/logging/log_config.toml
"""
path = os.path.join(_path, "log_config.toml")
return path
def show_system_config():
"""
This function opens the logging configuration file in the system-default browser.
"""
# pylint:disable = import-outside-toplevel
import webbrowser
webbrowser.open(config_path())
[docs]def edit_system_config(wait_on_close=False):
"""
This function opens the log configuration file using OS-specific editors.
Setting the ``EDITOR`` environment variable will override ``xdg-open/open`` on
Linux and MacOS, and allows use of ``wait_on_close`` for editor close before
continuing execution.
.. warning::
As each OS configuration differs user-to-user, you may wish to
instead open this file manually with the ``config_path()`` provided path.
"""
if editor := os.getenv("EDITOR"):
# pylint:disable = consider-using-with
with subprocess.Popen((editor, config_path())) as p:
if wait_on_close: # Only valid when editor is known
p.wait()
# pylint:disable = superfluous-parens
elif (s := platform.system()) in ["Linux", "Darwin"]:
f_cmd = None
if s == "Linux":
f_cmd = "xdg-open"
else:
f_cmd = "open"
subprocess.Popen((f_cmd, config_path()))
else: # Windows-only, does not exist on MacOS/Linux
os.startfile(config_path()) # pylint:disable = no-member
_modules/pennylane/logging/configuration
Download Python script
Download Notebook
View on GitHub