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

Subversion Repositories radiohdl

[/] [radiohdl/] [trunk/] [base/] [hdl_raw_access.py] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 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: hdl_raw_access.py 18619 2018-07-24 08:41:55Z overeem $
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
class RawConfigFile(object):
38
    """
39
    Class that holds the raw content of a configfile. To simplify the manipulation of the
40
    content the file is internally stored as lines.
41
    """
42
    def __init__(self, filename):
43
        """
44
        Read the hdl configuration file and check presence of the required keys.
45
        :raise ConfigFileException
46
        """
47
        full_filename = os.path.expanduser(os.path.expandvars(filename))
48
        if not os.path.isfile(full_filename):
49
            raise ConfigFileException ("configfile '%s' not found" % full_filename)
50
 
51
        self.filename = full_filename
52
        self.content  = open(self.filename, 'r').readlines()
53
 
54
    @property
55
    def ID(self):
56
        "Returns uniq ID (string) to identify this particular file. Fullfilename is used."
57
        return self.filename
58
 
59
    def _save_content(self, verbose=False):
60
        """
61
        Write the content to the file.
62
        """
63
        with open(self.filename, 'w') as fp:
64
            fp.writelines(self.content)
65
 
66
        if verbose:
67
            print self.filename
68
 
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),
93
                               self.content[linenr]):
94
                   self.content.pop(linenr)
95
               else:
96
                   break
97
 
98
            self._save_content(verbose)
99
            break
100
 
101
 
102
    def append_key_value(self, key, value, verbose):
103
        """
104
        Append the given key and value to the end of the configfile.
105
        \n characters can be used both in the key and the value to start at a new line.
106
        """
107
        self.content.append("{} {} {}\n".format(key.replace("\\n","\n"),
108
                                                CFG_ASSIGNMENT_CHAR,
109
                                                value.replace("\\n","\n")))
110
        self._save_content(verbose)
111
 
112
 
113
    def rename_key(self, old_key, new_key, verbose):
114
        """
115
        Change the name of a key.
116
        """
117
        # Search the key in the lines
118
        prog = re.compile("^{}[ \t]*{}".format(old_key, CFG_ASSIGNMENT_CHAR))
119
        for (linenr, line) in enumerate(self.content):
120
            # search if line starts with this old_key
121
            match = prog.search(line)
122
            if not match:
123
                continue
124
 
125
            # change the name of the key
126
            value_start = match.end()
127
            line = "{} {}{}\n".format(new_key.replace("\\n", "\n"), CFG_ASSIGNMENT_CHAR, line[value_start:])
128
            self.content[linenr] = line
129
            self._save_content(verbose)
130
            break
131
 
132
    def remove_key(self, key,verbose):
133
        """
134
        Remove a key and value pair from the dictfile.
135
        """
136
        # difficulty here is that we can delete the lines immediately because the enumeration over the
137
        # file content gets messed up. So we setup the variables first_line and last_line that mark
138
        # the part of the list that has to be removed. After the enumeration we cut the lines.
139
 
140
        # First search the key in the lines
141
        searching_key     = True
142
        last_line         = len(self.content)
143
        key_mask          = re.compile(r"^{}[ \t]*{}".format(key, CFG_ASSIGNMENT_CHAR))
144
        end_of_value_mask = re.compile(r"(\[[a-zA-Z0-9_]+\]|[a-zA-Z0-9_]+[ \t]*{})".format(CFG_ASSIGNMENT_CHAR))
145
        for (linenr, line) in enumerate(self.content):
146
            if searching_key:
147
                # search if line starts with this key
148
                match = key_mask.search(line)
149
                if match:
150
                    first_line = linenr
151
                    searching_key = False
152
            else:
153
                # not searching for the key anymore, we now have to find the and of the value.
154
                # to support removing old multiline values we have to skip lines until we find a
155
                # sectionheader|other key or are at the end of the file
156
               if not end_of_value_mask.match(self.content[linenr]):
157
                   continue
158
               last_line = linenr
159
               break
160
 
161
        del self.content[first_line:last_line]
162
        self._save_content(verbose)
163
 
164
 
165
    def insert_key_at_linenr(self, new_key, new_value, linenumber, verbose):
166
        """
167
        Insert a new key = value pair in the configfile at linenumber. The first line has number 1.
168
        """
169
        if linenumber > len(self.content):
170
            return self.append_key_value(new_key, new_value, verbose)
171
 
172
        # Read dict file into string and insert new key = value pair at insertLineNr
173
        new_line = "{} {} {}\n".format(new_key.replace("\\n", "\n"), CFG_ASSIGNMENT_CHAR, new_value)
174
        self.content.insert(linenumber-1, new_line)
175
        self._save_content(verbose)
176
 
177
 
178
    def insert_key_value_before_key(self, new_key, new_value, before_key, verbose):
179
        """
180
        Insert a new key = value pair in the configfile just before another key..
181
        """
182
        # Search the key in the lines
183
        prog = re.compile("^{}[ \t]*{}".format(before_key, CFG_ASSIGNMENT_CHAR))
184
        for (linenr, line) in enumerate(self.content):
185
            # search if line starts with this key
186
            match = prog.search(line)
187
            if not match:
188
                continue
189
 
190
            return self.insert_key_at_linenr(new_key, new_value, linenr+1, verbose)
191
 
192
 
193
class RawConfigTree(ConfigTree):
194
    """
195
    Class the represents the collection of 'raw content' configfiles.
196
    """
197
    def __init__(self, rootdirs, filename, sections=None):
198
        """
199
        Read the raw configuration files and stores them in this tree.
200
        :raise ConfigFileException
201
        """
202
        super(RawConfigTree, self).__init__(rootdirs, filename, sections)
203
 
204
    def _factory_constructor(self, full_filename):
205
        "Function for returning the readin configfile."
206
        return RawConfigFile(full_filename)
207
 
208
 
209
 

powered by: WebSVN 2.1.0

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