# Copyright 2018-2021 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.r"""This module contains the :class:`Configuration` class, which is used toload, store, save, and modify configuration options for PennyLane and allsupported plugins and devices."""importcontextlibimportosimporttomlkitastomlfromappdirsimportuser_config_dir
[docs]classConfiguration:"""Configuration class. This class is responsible for loading, saving, and storing PennyLane and plugin/device configurations. Args: name (str): filename of the configuration file. This should be a valid TOML file. You may also pass an absolute or a relative file path to the configuration file. """def__init__(self,name):# Look for an existing configuration fileself._config={}self._filepath=Noneself._name=nameself._user_config_dir=user_config_dir("pennylane","Xanadu")self._env_config_dir=os.environ.get("PENNYLANE_CONF","")# search the current directory the directory under environment# variable PENNYLANE_CONF, and default user config directory, in that order.directories=[os.curdir,self._env_config_dir,self._user_config_dir,""]fordirectoryindirectories:withcontextlib.suppress(FileNotFoundError):self._filepath=os.path.join(directory,self._name)self.load(self._filepath)breakdef__str__(self):ifself._config:returnf"{self._config}"return""def__repr__(self):returnf"PennyLane Configuration <{self._filepath}>"@propertydefpath(self):"""Return the path of the loaded configuration file. Returns: str: If no configuration is loaded, this returns ``None``."""returnself._filepath
[docs]defload(self,filepath):"""Load a configuration file. Args: filepath (str): path to the configuration file. """withopen(filepath,"r",encoding="utf8")asf:self._config=toml.load(f)
[docs]defsave(self,filepath):"""Save a configuration file. Args: filepath (str): path to the configuration file. """withopen(filepath,"w",encoding="utf8")asf:toml.dump(self._config,f)
[docs]@staticmethoddefsafe_set(dct,value,*keys):"""Safely set the value of a key from a nested dictionary. If any key provided does not exist, a dictionary containing the remaining keys is dynamically created and set to the required value. Args: dct (dict): the dictionary to set the value of. value: the value to set. Can be any valid type. *keys: each additional argument corresponds to a nested key. """forkeyinkeys[:-1]:dct=dct.setdefault(key,{})dct[keys[-1]]=value
[docs]@staticmethoddefsafe_get(dct,*keys):"""Safely return value from a nested dictionary. If any key provided does not exist, an empty dictionary is returned. Args: dct (dict): the dictionary to set the value of. *keys: each additional argument corresponds to a nested key. Returns: value corresponding to ``dct[keys[0]][keys[1]]`` etc. """forkeyinkeys:try:dct=dct[key]exceptKeyError:return{}returndct