python-igraph manual

For using igraph from Python

   Home       Trees       Indices       Help   
Package igraph :: Module configuration
[hide private]

Source Code for Module igraph.configuration

  1  # vim:ts=4:sw=4:sts=4:et 
  2  # -*- coding: utf-8 -*- 
  3  """ 
  4  Configuration framework for igraph. 
  5   
  6  igraph has some parameters which usually affect the behaviour of many functions. 
  7  This module provides the framework for altering and querying igraph parameters 
  8  as well as saving them to and retrieving them from disk. 
  9  """ 
 10   
 11  __license__ = """\ 
 12  Copyright (C) 2006-2012  Tamás Nepusz <ntamas@gmail.com> 
 13  Pázmány Péter sétány 1/a, 1117 Budapest, Hungary 
 14   
 15  This program is free software; you can redistribute it and/or modify 
 16  it under the terms of the GNU General Public License as published by 
 17  the Free Software Foundation; either version 2 of the License, or 
 18  (at your option) any later version. 
 19   
 20  This program is distributed in the hope that it will be useful, 
 21  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 22  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 23  GNU General Public License for more details. 
 24   
 25  You should have received a copy of the GNU General Public License 
 26  along with this program; if not, write to the Free Software 
 27  Foundation, Inc.,  51 Franklin Street, Fifth Floor, Boston, MA 
 28  02110-1301 USA 
 29  """ 
 30   
 31  from ConfigParser import SafeConfigParser 
 32  import platform 
 33  import os.path 
34 35 36 -def get_platform_image_viewer():
37 """Returns the path of an image viewer on the given platform""" 38 plat = platform.system() 39 if plat == "Darwin": 40 # Most likely Mac OS X 41 return "open" 42 elif plat == "Linux": 43 # Linux has a whole lot of choices, try to find one 44 choices = ["eog", "gthumb", "gqview", "kuickshow", "xnview", "display", 45 "gpicview", "gwenview", "qiv", "gimv", "ristretto"] 46 paths = ["/usr/bin", "/bin"] 47 for path in paths: 48 for choice in choices: 49 full_path = os.path.join(path, choice) 50 if os.path.isfile(full_path): 51 return full_path 52 return "" 53 elif plat == "Windows" or plat == "Microsoft": # Thanks to Dale Hunscher 54 # Use the built-in Windows image viewer, if available 55 return "start" 56 else: 57 # Unknown system 58 return "" 59
60 61 -class Configuration(object):
62 """Class representing igraph configuration details. 63 64 General ideas 65 ============= 66 67 The configuration of igraph is stored in the form of name-value pairs. 68 This object provides an interface to the configuration data using the 69 syntax known from dict: 70 71 >>> c=Configuration() 72 >>> c["general.verbose"] = True 73 >>> print c["general.verbose"] 74 True 75 76 Configuration keys are organized into sections, and the name to be used 77 for a given key is always in the form C{section.keyname}, like 78 C{general.verbose} in the example above. In that case, C{general} is the 79 name of the configuration section, and C{verbose} is the name of the key. 80 If the name of the section is omitted, it defaults to C{general}, so 81 C{general.verbose} can be referred to as C{verbose}: 82 83 >>> c=Configuration() 84 >>> c["verbose"] = True 85 >>> print c["general.verbose"] 86 True 87 88 User-level configuration is stored in C{~/.igraphrc} per default on Linux 89 and Mac OS X systems, or in C{C:\\Documents and Settings\\username\\.igraphrc} 90 on Windows systems. However, this configuration is read only when C{igraph} 91 is launched through its shell interface defined in L{igraph.app.shell}. 92 This behaviour might change before version 1.0. 93 94 Known configuration keys 95 ======================== 96 97 The known configuration keys are presented below, sorted by section. When 98 referring to them in program code, don't forget to add the section name, 99 expect in the case of section C{general}. 100 101 General settings 102 ---------------- 103 104 These settings are all stored in section C{general}. 105 106 - B{shells}: the list of preferred Python shells to be used with the 107 command-line C{igraph} script. The shells in the list are tried one 108 by one until any of them is found on the system. C{igraph} functions 109 are then imported into the main namespace of the shell and the shell 110 is launched. Known shells and their respective class names to be 111 used can be found in L{igraph.app.shell}. Example: 112 C{IPythonShell, ClassicPythonShell}. This is the default, by the way. 113 - B{verbose}: whether L{igraph} should talk more than really necessary. 114 For instance, if set to C{True}, some functions display progress bars. 115 116 Application settings 117 -------------------- 118 119 These settings specify the external applications that are possibly 120 used by C{igraph}. They are all stored in section C{apps}. 121 122 - B{image_viewer}: image viewer application. If set to an empty string, 123 it will be determined automatically from the platform C{igraph} runs 124 on. On Mac OS X, it defaults to the Preview application. On Linux, 125 it chooses a viewer from several well-known Linux viewers like 126 C{gthumb}, C{kuickview} and so on (see the source code for the full 127 list). On Windows, it defaults to the system's built-in image viewer. 128 129 Plotting settings 130 ----------------- 131 132 These settings specify the default values used by plotting functions. 133 They are all stored in section C{plotting}. 134 135 - B{layout}: default graph layout algorithm to be used. 136 137 - B{mark_groups}: whether to mark the clusters by polygons when 138 plotting a clustering object. 139 140 - B{palette}: default palette to be used for converting integer 141 numbers to colors. See L{colors.Palette} for more information. 142 Valid palette names are stored in C{colors.palettes}. 143 144 - B{wrap_labels}: whether to try to wrap the labels of the 145 vertices automatically if they don't fit within the vertex. 146 Default: C{False}. 147 148 Remote repository settings 149 -------------------------- 150 151 These settings specify how igraph should access remote graph repositories. 152 Currently only the Nexus repository is supported. All these settings are 153 stored in section C{remote}. 154 155 - B{nexus.url}: the root URL of the Nexus repository. Default: 156 C{http://nexus.igraph.org}. 157 158 Shell settings 159 -------------- 160 161 These settings specify options for external environments in which igraph is 162 embedded (e.g., IPython and its Qt console). These settings are stored in 163 section C{shell}. 164 165 - B{ipython.inlining.Plot}: whether to show instances of the L{Plot} class 166 inline in IPython's console if the console supports it. Default: C{True} 167 168 @undocumented: _item_to_section_key, _types, _sections, _definitions, _instance 169 """ 170 171 # pylint: disable-msg=R0903 172 # R0903: too few public methods
173 - class Types(object):
174 """Static class for the implementation of custom getter/setter functions 175 for configuration keys""" 176
177 - def __init__(self):
178 pass 179 180 @staticmethod
181 - def setboolean(obj, section, key, value):
182 """Sets a boolean value in the given configuration object. 183 184 @param obj: a configuration object 185 @param section: the section of the value to be set 186 @param key: the key of the value to be set 187 @param value: the value itself. C{0}, C{false}, C{no} and C{off} 188 means false, C{1}, C{true}, C{yes} and C{on} means true, 189 everything else results in a C{ValueError} being thrown. 190 Values are case insensitive 191 """ 192 value = str(value).lower() 193 if value in ("0", "false", "no", "off"): 194 value = "false" 195 elif value in ("1", "true", "yes", "on"): 196 value = "true" 197 else: 198 raise ValueError("value cannot be coerced to boolean type") 199 obj.set(section, key, value) 200 201 @staticmethod
202 - def setint(obj, section, key, value):
203 """Sets an integer value in the given configuration object. 204 205 @param obj: a configuration object 206 @param section: the section of the value to be set 207 @param key: the key of the value to be set 208 @param value: the value itself. 209 """ 210 obj.set(section, key, str(int(value))) 211 212 @staticmethod
213 - def setfloat(obj, section, key, value):
214 """Sets a float value in the given configuration object. 215 216 Note that float values are converted to strings in the configuration 217 object, which may lead to some precision loss. 218 219 @param obj: a configuration object 220 @param section: the section of the value to be set 221 @param key: the key of the value to be set 222 @param value: the value itself. 223 """ 224 obj.set(section, key, str(float(value)))
225 226 _types = { 227 "boolean": { 228 "getter": SafeConfigParser.getboolean, 229 "setter": Types.setboolean 230 }, 231 "int": { 232 "getter": SafeConfigParser.getint, 233 "setter": Types.setint 234 }, 235 "float": { 236 "getter": SafeConfigParser.getfloat, 237 "setter": Types.setfloat 238 } 239 } 240 241 _sections = ("general", "apps", "plotting", "remote", "shell") 242 _definitions = { 243 "general.shells": { 244 "default": "IPythonShell,ClassicPythonShell" 245 }, 246 "general.verbose": { 247 "default": True, 248 "type": "boolean" 249 }, 250 251 "apps.image_viewer": { 252 "default": get_platform_image_viewer() 253 }, 254 255 "plotting.layout": { 256 "default": "auto" 257 }, 258 "plotting.mark_groups": { 259 "default": False, 260 "type": "boolean" 261 }, 262 "plotting.palette": { 263 "default": "gray" 264 }, 265 "plotting.wrap_labels": { 266 "default": False, 267 "type": "boolean" 268 }, 269 270 "remote.nexus.url": { 271 "default": "http://nexus.igraph.org" 272 }, 273 274 "shell.ipython.inlining.Plot": { 275 "default": True, 276 "type": "boolean" 277 } 278 } 279 280 # The singleton instance we are using throughout other modules 281 _instance = None 282
283 - def __init__(self, filename=None):
284 """Creates a new configuration instance. 285 286 @param filename: file or file pointer to be read. Can be omitted. 287 """ 288 self._config = SafeConfigParser() 289 self._filename = None 290 291 # Create default sections 292 for sec in self._sections: 293 self._config.add_section(sec) 294 # Create default values 295 for name, definition in self._definitions.iteritems(): 296 if "default" in definition: 297 self[name] = definition["default"] 298 299 if filename is not None: 300 self.load(filename) 301 302 @property
303 - def filename(self):
304 """Returns the filename associated to the object. 305 306 It is usually the name of the configuration file that was used when 307 creating the object. L{Configuration.load} always overwrites it with 308 the filename given to it. If C{None}, the configuration was either 309 created from scratch or it was updated from a stream without name 310 information.""" 311 return self._filename 312
313 - def _get(self, section, key):
314 """Internal function that returns the value of a given key in a 315 given section.""" 316 definition = self._definitions.get("%s.%s" % (section, key), {}) 317 getter = None 318 if "type" in definition: 319 getter = self._types[definition["type"]].get("getter") 320 if getter is None: 321 getter = self._config.__class__.get 322 return getter(self._config, section, key) 323 324 @staticmethod
325 - def _item_to_section_key(item):
326 """Converts an item description to a section-key pair. 327 328 @param item: the item to be converted 329 @return: if C{item} contains a period (C{.}), it is splitted into two parts 330 at the first period, then the two parts are returned, so the part before 331 the period is the section. If C{item} does not contain a period, the 332 section is assumed to be C{general}, and the second part of the returned 333 pair contains C{item} unchanged""" 334 if "." in item: 335 section, key = item.split(".", 1) 336 else: 337 section, key = "general", item 338 return section, key 339
340 - def __contains__(self, item):
341 """Checks whether the given configuration item is set. 342 343 @param item: the configuration key to check. 344 @return: C{True} if the key has an associated value, C{False} otherwise. 345 """ 346 section, key = self._item_to_section_key(item) 347 return self._config.has_option(section, key) 348
349 - def __getitem__(self, item):
350 """Returns the given configuration item. 351 352 @param item: the configuration key to retrieve. 353 @return: the configuration value""" 354 section, key = self._item_to_section_key(item) 355 if key == "*": 356 # Special case: retrieving all the keys within a section and 357 # returning it in a dict 358 keys = self._config.items(section) 359 return dict((key, self._get(section, key)) for key, _ in keys) 360 else: 361 return self._get(section, key) 362
363 - def __setitem__(self, item, value):
364 """Sets the given configuration item. 365 366 @param item: the configuration key to set 367 @param value: the new value of the configuration key 368 """ 369 section, key = self._item_to_section_key(item) 370 definition = self._definitions.get("%s.%s" % (section, key), {}) 371 setter = None 372 if "type" in definition: 373 setter = self._types[definition["type"]].get("setter", None) 374 if setter is None: 375 setter = self._config.__class__.set 376 return setter(self._config, section, key, value) 377
378 - def __delitem__(self, item):
379 """Deletes the given item from the configuration. 380 381 If the item has a default value, the default value is written back instead 382 of the current value. Without a default value, the item is really deleted. 383 """ 384 section, key = self._item_to_section_key(item) 385 definition = self._definitions.get("%s.%s" % (section, key), {}) 386 if "default" in definition: 387 self[item] = definition["default"] 388 else: 389 self._config.remove_option(section, key) 390
391 - def has_key(self, item):
392 """Checks if the configuration has a given key. 393 394 @param item: the key being sought""" 395 if "." in item: 396 section, key = item.split(".", 1) 397 else: 398 section, key = "general", item 399 return self._config.has_option(section, key) 400
401 - def load(self, stream=None):
402 """Loads the configuration from the given file. 403 404 @param stream: name of a file or a file object. The configuration will be loaded 405 from here. Can be omitted, in this case, the user-level configuration is 406 loaded. 407 """ 408 stream = stream or get_user_config_file() 409 if isinstance(stream, basestring): 410 stream = open(stream, "r") 411 file_was_open = True 412 self._config.readfp(stream) 413 self._filename = getattr(stream, "name", None) 414 if file_was_open: 415 stream.close() 416
417 - def save(self, stream=None):
418 """Saves the configuration. 419 420 @param stream: name of a file or a file object. The configuration will be saved 421 there. Can be omitted, in this case, the user-level configuration file will 422 be overwritten. 423 """ 424 stream = stream or get_user_config_file() 425 if not hasattr(stream, "write") or not hasattr(stream, "close"): 426 stream = open(stream, "w") 427 file_was_open = True 428 self._config.write(stream) 429 if file_was_open: 430 stream.close() 431 432 @classmethod
433 - def instance(cls):
434 """Returns the single instance of the configuration object.""" 435 if cls._instance is None: 436 cfile = get_user_config_file() 437 try: 438 config = cls(cfile) 439 except IOError: 440 # No config file yet, whatever 441 config = cls() 442 cls._instance = config 443 return cls._instance
444
445 446 -def get_user_config_file():
447 """Returns the path where the user-level configuration file is stored""" 448 return os.path.expanduser("~/.igraphrc") 449
450 451 -def init():
452 """Default mechanism to initiate igraph configuration 453 454 This method loads the user-specific configuration file from the 455 user's home directory, or if it does not exist, creates a default 456 configuration. 457 458 The method is safe to be called multiple times, it will not parse 459 the configuration file twice. 460 461 @return: the L{Configuration} object loaded or created.""" 462 return Configuration.instance() 463

   Home       Trees       Indices       Help