OpenCores
URL https://opencores.org/ocsvn/radiohdl/radiohdl/trunk

Subversion Repositories radiohdl

[/] [radiohdl/] [trunk/] [core/] [hdl_raw_access.py] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 danv
###############################################################################
2
#
3
# Copyright (C) 2014-2018
4
# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
5
# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
6
#
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
#
20
# $Id$
21
#
22
###############################################################################
23
 
24
import re
25
import os.path
26
from configfile import *
27
from configtree import ConfigTree
28
 
29
__all__ = ['RawConfigFile', 'RawConfigTree']
30
 
31
"""
32
File that implements the configfile <-> configtree concept but this time with the
33
intention to modify the keys and/or values in those configfiles. So the content of
34
the configfiels is kept as raw as possible.
35
"""
36
 
37
 
38
class RawConfigFile(object):
39
    """
40
    Class that holds the raw content of a configfile. To simplify the manipulation of the
41
    content the file is internally stored as lines.
42
    """
43
    def __init__(self, filename):
44
        """
45
        Read the hdl configuration file and check presence of the required keys.
46
        :raise ConfigFileException
47
        """
48
        full_filename = os.path.expanduser(os.path.expandvars(filename))
49
        if not os.path.isfile(full_filename):
50
            raise ConfigFileException("configfile '%s' not found" % full_filename)
51
 
52
        self.filename = full_filename
53
        self.content  = open(self.filename, 'r').readlines()
54
 
55
    @property
56
    def ID(self):
57
        "Returns uniq ID (string) to identify this particular file. Fullfilename is used."
58
        return self.filename
59
 
60
    def _save_content(self, verbose=False):
61
        """
62
        Write the content to the file.
63
        """
64
        with open(self.filename, 'w') as fp:
65
            fp.writelines(self.content)
66
 
67
        if verbose:
68
            print(self.filename)
69
 
70
    def change_value(self, key, new_value, verbose):
71
        """
72
        Change the value of the given key. The old value may be empty, be on one or multiple lines.
73
        The new value may use \n characters to create a new multiline value.
74
        """
75
        # Search the key in the lines
76
        prog = re.compile("^{}[ \t]*{}".format(key, CFG_ASSIGNMENT_CHAR))
77
        for (linenr, line) in enumerate(self.content):
78
            # search if line starts with this key
79
            match = prog.search(line)
80
            if not match:
81
                continue
82
 
83
            # replace the value that is on this line with the whole new value
84
            value_start = match.end()
85
            line = line[0:value_start] + ' ' + new_value.replace("\\n", "\n") + "\n"
86
            self.content[linenr] = line
87
 
88
            # to support removing old multiline values we have to skip lines until we find a
89
            # sectionheader|other key|empty line or are at the end of the file
90
            linenr += 1
91
            while linenr < len(self.content):
92
                if not re.match(r"(\[[a-zA-Z0-9_]+\]|[a-zA-Z0-9_]+[ \t]*{}|^[ \t]*$)".format(CFG_ASSIGNMENT_CHAR), self.content[linenr]):
93
                    self.content.pop(linenr)
94
                else:
95
                    break
96
 
97
            self._save_content(verbose)
98
            break
99
 
100
    def append_key_value(self, key, value, verbose):
101
        """
102
        Append the given key and value to the end of the configfile.
103
        \n characters can be used both in the key and the value to start at a new line.
104
        """
105
        self.content.append("{} {} {}\n".format(key.replace("\\n", "\n"),
106
                                                CFG_ASSIGNMENT_CHAR,
107
                                                value.replace("\\n", "\n")))
108
        self._save_content(verbose)
109
 
110
    def rename_key(self, old_key, new_key, verbose):
111
        """
112
        Change the name of a key.
113
        """
114
        # Search the key in the lines
115
        prog = re.compile("^{}[ \t]*{}".format(old_key, CFG_ASSIGNMENT_CHAR))
116
        for (linenr, line) in enumerate(self.content):
117
            # search if line starts with this old_key
118
            match = prog.search(line)
119
            if not match:
120
                continue
121
 
122
            # change the name of the key
123
            value_start = match.end()
124
            line = "{} {}{}\n".format(new_key.replace("\\n", "\n"), CFG_ASSIGNMENT_CHAR, line[value_start:])
125
            self.content[linenr] = line
126
            self._save_content(verbose)
127
            break
128
 
129
    def remove_key(self, key, verbose):
130
        """
131
        Remove a key and value pair from the dictfile.
132
        """
133
        # difficulty here is that we can delete the lines immediately because the enumeration over the
134
        # file content gets messed up. So we setup the variables first_line and last_line that mark
135
        # the part of the list that has to be removed. After the enumeration we cut the lines.
136
 
137
        # First search the key in the lines
138
        searching_key     = True
139
        last_line         = len(self.content)
140
        key_mask          = re.compile(r"^{}[ \t]*{}".format(key, CFG_ASSIGNMENT_CHAR))
141
        end_of_value_mask = re.compile(r"(\[[a-zA-Z0-9_]+\]|[a-zA-Z0-9_]+[ \t]*{})".format(CFG_ASSIGNMENT_CHAR))
142
        for (linenr, line) in enumerate(self.content):
143
            if searching_key:
144
                # search if line starts with this key
145
                match = key_mask.search(line)
146
                if match:
147
                    first_line = linenr
148
                    searching_key = False
149
            else:
150
                # not searching for the key anymore, we now have to find the and of the value.
151
                # to support removing old multiline values we have to skip lines until we find a
152
                # sectionheader|other key or are at the end of the file
153
                if not end_of_value_mask.match(self.content[linenr]):
154
                    continue
155
                last_line = linenr
156
                break
157
 
158
        del self.content[first_line:last_line]
159
        self._save_content(verbose)
160
 
161
    def insert_key_at_linenr(self, new_key, new_value, linenumber, verbose):
162
        """
163
        Insert a new key = value pair in the configfile at linenumber. The first line has number 1.
164
        """
165
        if linenumber > len(self.content):
166
            return self.append_key_value(new_key, new_value, verbose)
167
 
168
        # Read dict file into string and insert new key = value pair at insertLineNr
169
        new_line = "{} {} {}\n".format(new_key.replace("\\n", "\n"), CFG_ASSIGNMENT_CHAR, new_value)
170
        self.content.insert(linenumber-1, new_line)
171
        self._save_content(verbose)
172
 
173
    def insert_key_value_before_key(self, new_key, new_value, before_key, verbose):
174
        """
175
        Insert a new key = value pair in the configfile just before another key..
176
        """
177
        # Search the key in the lines
178
        prog = re.compile("^{}[ \t]*{}".format(before_key, CFG_ASSIGNMENT_CHAR))
179
        for (linenr, line) in enumerate(self.content):
180
            # search if line starts with this key
181
            match = prog.search(line)
182
            if not match:
183
                continue
184
 
185
            return self.insert_key_at_linenr(new_key, new_value, linenr+1, verbose)
186
 
187
 
188
class RawConfigTree(ConfigTree):
189
    """
190
    Class the represents the collection of 'raw content' configfiles.
191
    """
192
    def __init__(self, rootdirs, filename, sections=None):
193
        """
194
        Read the raw configuration files and stores them in this tree.
195
        :raise ConfigFileException
196
        """
197
        super(RawConfigTree, self).__init__(rootdirs, filename, sections)
198
 
199
    def _factory_constructor(self, full_filename):
200
        "Function for returning the readin configfile."
201
        return RawConfigFile(full_filename)

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.