source: rtems-tools/rtemstoolkit/configuration.py @ e058db0

Last change on this file since e058db0 was e058db0, checked in by Chris Johns <chrisj@…>, on Nov 7, 2018 at 3:55:20 AM

python: Provide support to select a valid python version.

  • Update imports after wrapping the code.
  • Fix python3 issues.
  • Fix config path issues for in repo and install runs.

Closes #3537

  • Property mode set to 100644
File size: 6.2 KB
Line 
1#
2# RTEMS Tools Project (http://www.rtems.org/)
3# Copyright 2017 Chris Johns (chrisj@rtems.org)
4# All rights reserved.
5#
6# This file is part of the RTEMS Tools package in 'rtems-tools'.
7#
8# Redistribution and use in source and binary forms, with or without
9# modification, are permitted provided that the following conditions are met:
10#
11# 1. Redistributions of source code must retain the above copyright notice,
12# this list of conditions and the following disclaimer.
13#
14# 2. Redistributions in binary form must reproduce the above copyright notice,
15# this list of conditions and the following disclaimer in the documentation
16# and/or other materials provided with the distribution.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28# POSSIBILITY OF SUCH DAMAGE.
29#
30
31#
32# Host specifics.
33#
34
35from __future__ import print_function
36
37import os
38import re
39
40from rtemstoolkit import error
41from rtemstoolkit import path
42
43class configuration:
44
45    def __init__(self, raw = True):
46        self.raw = True
47        try:
48            import configparser
49            self.config = configparser.ConfigParser(strict = False)
50        except:
51            # python2
52            import ConfigParser as configparser
53            self.config = configparser.ConfigParser()
54        self.ini = None
55        self.macro_filter = re.compile('\$\{.+\}')
56
57    def __str__(self):
58        if self.ini is None:
59            return 'empty'
60        s = ['Base: %s' % (self.ini['base'])]
61        s += ['Files:']
62        for f in self.ini['files']:
63            s += [' %s' % (f)]
64        s += ['Defaults:']
65        for default in self.config.defaults():
66            s += ' ' + default
67        s += ['Sections:']
68        for section in self.config.sections():
69            s += [' [%s]' % (section)]
70            for option in self.config.options(section):
71                s += [%s = %s' % (option,
72                                     self.config.get(section,
73                                                     option,
74                                                     raw = self.raw))]
75        return os.linesep.join(s)
76
77    def get_item(self, section, label, err = True):
78        try:
79            rec = self.config.get(section, label, raw = self.raw).replace(os.linesep, ' ')
80        except:
81            if err:
82                raise error.general('config: no "%s" found in "%s"' % (label, section))
83            return None
84        #
85        # On Python 2.7 there is no extended interpolation so add support here.
86        # On Python 3 this should happen automatically and so the findall
87        # should find nothing.
88        #
89        for m in self.macro_filter.findall(rec):
90            if ':' not in m:
91                raise error.general('config: interpolation is ${section:value}: %s' % (m))
92            section_value = m[2:-1].split(':')
93            if len(section_value) != 2:
94                raise error.general('config: interpolation is ${section:value}: %s' % (m))
95            try:
96                ref = self.config.get(section_value[0],
97                                      section_value[1],
98                                      raw = self.raw).replace(os.linesep, ' ')
99                rec = rec.replace(m, ref)
100            except:
101                pass
102        return rec
103
104    def get_items(self, section, err = True, flatten = True):
105        try:
106            items = []
107            for name, key in self.config.items(section, raw = self.raw):
108                if flatten:
109                    items += [(name, key.replace(os.linesep, ' '))]
110                else:
111                    items += [(name, key)]
112            return items
113        except:
114            if err:
115                raise error.general('config: section "%s" not found' % (section))
116        return []
117
118    def comma_list(self, section, label, err = True):
119        items = self.get_item(section, label, err)
120        if items is None:
121            return []
122        return sorted(set([a.strip() for a in items.split(',')]))
123
124    def get_item_names(self, section, err = True):
125        try:
126            return [item[0] for item in self.config.items(section, raw = self.raw)]
127        except:
128            if err:
129                raise error.general('config: section "%s" not found' % (section))
130        return []
131
132    def has_section(self, section):
133        return self.config.has_section(section)
134
135    def load(self, name):
136        #
137        # Load all the files.
138        #
139        self.ini = { 'base'     : path.dirname(name),
140                     'files'    : [] }
141        includes = [name]
142        still_loading = True
143        while still_loading:
144            still_loading = False
145            for include in includes:
146                if not path.exists(include):
147                    rebased_inc = path.join(self.ini['base'],
148                                            path.basename(include))
149                    if not path.exists(rebased_inc):
150                        e = 'config: cannot find configuration: %s' % (include)
151                        raise error.general(e)
152                    include = rebased_inc
153                if include not in self.ini['files']:
154                    try:
155                        self.config.read(include)
156                    except configparser.ParsingError as ce:
157                        raise error.general('config: %s' % (ce))
158                    still_loading = True
159                    self.ini['files'] += [include]
160            includes = []
161            if still_loading:
162                for section in self.config.sections():
163                    includes += self.comma_list(section, 'include', err = False)
164
165    def files(self):
166        return self.ini['files']
Note: See TracBrowser for help on using the repository browser.