Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/IPython/ConfigLoader.py
blob: d64864de360ec78de052634c2a4b22a3e47cd381 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# -*- coding: utf-8 -*-
"""Configuration loader
"""

#*****************************************************************************
#       Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
#
#  Distributed under the terms of the BSD License.  The full license is in
#  the file COPYING, distributed as part of this software.
#*****************************************************************************

import exceptions
import os
from pprint import pprint

from IPython import ultraTB
from IPython.ipstruct import Struct
from IPython.genutils import *

class ConfigLoaderError(exceptions.Exception):
    """Exception for ConfigLoader class."""

    def __init__(self,args=None):
        self.args = args

class ConfigLoader:

    """Configuration file loader capable of handling recursive inclusions and
    with parametrized conflict resolution for multiply found keys."""

    def __init__(self,conflict=None,field_sep=None,reclimit=15):

        """The reclimit parameter controls the number of recursive
        configuration file inclusions. This way we can stop early on (before
        python's own recursion limit is hit) if there is a circular
        inclusion.

        - conflict: dictionary for conflict resolutions (see Struct.merge())

        """
        self.conflict = conflict
        self.field_sep = field_sep
        self.reset(reclimit)
        
    def reset(self,reclimit=15):
        self.reclimit = reclimit
        self.recdepth = 0
        self.included = []
        
    def load(self,fname,convert=None,recurse_key='',incpath = '.',**kw):
        """Load a configuration file, return the resulting Struct.

        Call: load_config(fname,convert=None,conflict=None,recurse_key='')

         - fname: file to load from.
         - convert: dictionary of type conversions (see read_dict())
         - recurse_key: keyword in dictionary to trigger recursive file
         inclusions.
         """

        if self.recdepth > self.reclimit:
            raise ConfigLoaderError, 'maximum recursive inclusion of rcfiles '+\
                  'exceeded: ' + `self.recdepth` + \
                  '.\nMaybe you have a circular chain of inclusions?'
        self.recdepth += 1
        fname = filefind(fname,incpath)
        data = Struct()
        # avoid including the same file more than once
        if fname in self.included:
            return data
        Xinfo = ultraTB.AutoFormattedTB(color_scheme='NoColor')
        if convert==None and recurse_key : convert = {qwflat:recurse_key}
        # for production, change warn to 0:
        data.merge(read_dict(fname,convert,fs=self.field_sep,strip=1,
                             warn=0,no_empty=0,**kw))
        # keep track of successfully loaded files
        self.included.append(fname)
        if recurse_key in data:
            for incfilename in data[recurse_key]:
                found=0
                try:
                    incfile = filefind(incfilename,incpath)
                except IOError:
                    if os.name in ['nt','dos']:
                        try:
                            # Try again with '.ini' extension
                            incfilename += '.ini'
                            incfile = filefind(incfilename,incpath)
                        except IOError:
                            found = 0
                        else:
                            found = 1
                    else:
                        found = 0
                else:
                    found = 1
                if found:
                    try:
                        data.merge(self.load(incfile,convert,recurse_key,
                                             incpath,**kw),
                                   self.conflict)
                    except:
                        Xinfo()
                        warn('Problem loading included file: '+
                             `incfilename` + '. Ignoring it...')
                else:
                    warn('File `%s` not found. Included by %s' % (incfilename,fname))

        return data

# end ConfigLoader