1# This file is part of QuTiP: Quantum Toolbox in Python. 2# 3# Copyright (c) 2011 and later, QuSTaR. 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are 8# met: 9# 10# 1. Redistributions of source code must retain the above copyright notice, 11# this list of conditions and the following disclaimer. 12# 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 17# 3. Neither the name of the QuTiP: Quantum Toolbox in Python nor the names 18# of its contributors may be used to endorse or promote products derived 19# from this software without specific prior written permission. 20# 21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 24# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32############################################################################### 33import os 34import qutip 35import qutip.settings as qset 36import qutip.solver as def_options 37import warnings 38try: 39 import ConfigParser as configparser #py27 40except: 41 import configparser #py3x 42from functools import partial 43 44 45def getcomplex(self, section, option): 46 return complex(self.get(section, option)) 47 48 49configparser.ConfigParser.getcomplex = getcomplex 50 51 52sections = [('qutip', qset)] 53 54 55def full_path(rc_file): 56 rc_file = os.path.expanduser(rc_file) 57 if os.path.isabs(rc_file): 58 return rc_file 59 qutip_conf_dir = os.path.join(os.path.expanduser("~"), '.qutip') 60 return os.path.join(qutip_conf_dir, rc_file) 61 62 63def has_qutip_rc(): 64 """ 65 Checks to see if the qutiprc file exists in the default 66 location, i.e. HOME/.qutip/qutiprc 67 """ 68 qutip_conf_dir = os.path.join(os.path.expanduser("~"), '.qutip') 69 if os.path.exists(qutip_conf_dir): 70 qutip_rc_file = os.path.join(qutip_conf_dir, "qutiprc") 71 qrc_exists = os.path.isfile(qutip_rc_file) 72 if qrc_exists: 73 return True, qutip_rc_file 74 else: 75 return False, '' 76 else: 77 return False, '' 78 79 80def generate_qutiprc(rc_file="qutiprc"): 81 """ 82 Generate a blank qutiprc file. 83 """ 84 # Check for write access to home dir 85 qutip_rc_file = full_path(rc_file) 86 qutip_conf_dir = os.path.dirname(qutip_rc_file) 87 os.makedirs(qutip_conf_dir, exist_ok=True) 88 89 if os.path.isfile(qutip_rc_file): 90 config = configparser.ConfigParser() 91 config.read(qutip_rc_file) 92 modified = False 93 for section, settings_object in sections: 94 if not config.has_section(section): 95 config.add_section(section) 96 modified = True 97 if modified: 98 with open(qutip_rc_file, 'w') as cfgfile: 99 config.write(cfgfile) 100 101 return modified 102 103 with open(qutip_rc_file,'w') as cfgfile: 104 config = configparser.ConfigParser() 105 for section, settings_object in sections: 106 config.add_section(section) 107 config.write(cfgfile) 108 return True 109 110 111def get_reader(val, config): 112 # The type of the read value is the same as the one presently loaded. 113 if isinstance(val, bool): 114 reader = config.getboolean 115 elif isinstance(val, int): 116 reader = config.getint 117 elif isinstance(val, float): 118 reader = config.getfloat 119 elif isinstance(val, complex): 120 reader = config.getcomplex 121 elif isinstance(val, str): 122 reader = config.get 123 return reader 124 125 126def has_rc_key(key, section=None, rc_file="qutiprc"): 127 """ 128 Verify if key exist in section of rc_file 129 """ 130 rc_file = full_path(rc_file) 131 if not os.path.isfile(rc_file): 132 return False 133 config = configparser.ConfigParser() 134 config.read(rc_file) 135 if section is None: 136 search_sections = [section for section, _ in sections] 137 else: 138 search_sections = [section] 139 for section in search_sections: 140 if config.has_section(section): 141 opts = config.options(section) 142 if key in opts: 143 return True 144 return False 145 146 147def write_rc_key(key, value, section='qutip', rc_file="qutiprc"): 148 """ 149 Writes a single key value to the qutiprc file 150 151 Parameters 152 ---------- 153 key : str 154 The key name to be written. 155 value : int/float/bool 156 Value corresponding to given key. 157 section : str 158 String for which settings object the key belong to. 159 Default : qutip 160 rc_file : str 161 String specifying file location. 162 Default : qutiprc 163 """ 164 rc_file = full_path(rc_file) 165 if not os.access(rc_file, os.W_OK): 166 warnings.warn("Does not have permissions to write config file") 167 return 168 config = configparser.ConfigParser() 169 config.read(rc_file) 170 if not config.has_section(section): 171 config.add_section(section) 172 config.set(section, key, str(value)) 173 174 with open(rc_file, 'w') as cfgfile: 175 config.write(cfgfile) 176 177 178def read_rc_key(key, datatype, section='qutip', rc_file="qutiprc"): 179 """ 180 Writes a single key value to the qutiprc file 181 182 Parameters 183 ---------- 184 key : str 185 The key name to be written. 186 datatype : 187 Type of the value corresponding to given key. 188 One of [int, float, bool, complex, str] 189 section : str 190 String for which settings object the key belong to. 191 rc_file : str 192 String specifying file location. 193 """ 194 rc_file = full_path(rc_file) 195 config = configparser.ConfigParser() 196 config.read(rc_file) 197 if not config.has_section(section): 198 raise ValueError("key not found") 199 reader = get_reader(datatype(0), config) 200 opts = config.options(section) 201 if key not in opts: 202 raise ValueError("key not found") 203 return reader(section, key) 204 205 206def write_rc_object(rc_file, section, object): 207 """ 208 Writes all keys and values corresponding to one object qutiprc file. 209 210 Parameters 211 ---------- 212 rc_file : str 213 String specifying file location. 214 section : str 215 Tags for the saved data. 216 object : Object 217 Object to save. All attribute's type must be one of bool, int, float, 218 complex, str. 219 """ 220 generate_qutiprc(rc_file) 221 config = configparser.ConfigParser() 222 config.read(full_path(rc_file)) 223 if not config.has_section(section): 224 config.add_section(section) 225 keys = object.__all 226 for key in keys: 227 config.set(section, key, str(getattr(object, key))) 228 with open(full_path(rc_file), 'w') as cfgfile: 229 config.write(cfgfile) 230 return 231 232 233def load_rc_object(rc_file, section, object): 234 """ 235 Read keys and values corresponding to one settings location 236 to the qutiprc file. 237 238 Parameters 239 ---------- 240 rc_file : str 241 String specifying file location. 242 section : str 243 Tags for the saved data. 244 object : Object 245 Object to overwrite. All attribute's type must be one of bool, int, 246 float, complex, str. 247 """ 248 config = configparser.ConfigParser() 249 config.read(full_path(rc_file)) 250 if not config.has_section(section): 251 raise configparser.NoSectionError(section) 252 keys = object.__all 253 opts = config.options(section) 254 for op in opts: 255 if op in keys: 256 reader = get_reader(getattr(object, op), config) 257 setattr(object, op, reader(section, op)) 258 else: 259 warnings.warn("Invalid qutip config variable in qutiprc: " + op) 260 261 262def write_rc_qset(rc_file): 263 """ 264 Writes qutip.settings in a qutiprc file. 265 266 Parameters 267 ---------- 268 rc_file : str 269 String specifying file location. 270 """ 271 write_rc_object(rc_file, "qutip", qset) 272 273 274def load_rc_qset(rc_file): 275 """ 276 Read qutip.settings to a qutiprc file. 277 278 Parameters 279 ---------- 280 rc_file : str 281 String specifying file location. 282 """ 283 load_rc_object(rc_file, "qutip", qset) 284 285 286def write_rc_config(rc_file): 287 """ 288 Writes all keys and values to the qutiprc file. 289 290 Parameters 291 ---------- 292 rc_file : str 293 String specifying file location. 294 """ 295 generate_qutiprc(rc_file) 296 297 config = configparser.ConfigParser() 298 config.read(full_path(rc_file)) 299 for section, settings_object in sections: 300 keys = settings_object.__all 301 for key in keys: 302 config.set(section, key, str(getattr(settings_object, key))) 303 304 with open(full_path(rc_file), 'w') as cfgfile: 305 config.write(cfgfile) 306 return 307 308 309def load_rc_config(rc_file): 310 """ 311 Loads the configuration data from the 312 qutiprc file 313 """ 314 config = configparser.ConfigParser() 315 config.read(full_path(rc_file)) 316 for section, settings_object in sections: 317 if config.has_section(section): 318 keys = settings_object.__all 319 opts = config.options(section) 320 for op in opts: 321 if op in keys: 322 reader = get_reader(getattr(settings_object, op), config) 323 setattr(settings_object, op, 324 reader(section, op)) 325 else: 326 warnings.warn("Invalid qutip config variable in qutiprc: " 327 + op) 328 # raise Exception('Invalid config variable in qutiprc.') 329 else: 330 warnings.warn("Section " + section + " not found ") 331 # raise configparser.NoSectionError('qutip') 332 333 if config.has_section('compiler'): 334 _valid_keys = ['CC', 'CXX'] 335 opts = config.options('compiler') 336 for op in opts: 337 up_op = op.upper() 338 if up_op in _valid_keys: 339 os.environ[up_op] = config.get('compiler', op) 340 else: 341 # raise Exception('Invalid config variable in qutiprc.') 342 warnings.warn("Invalid compiler config variable in qutiprc: " 343 + op) 344