author | Matt Mackall <mpm@selenic.com> |
Thu, 30 Apr 2009 19:22:06 -0500 | |
changeset 8265 | 52c5be55af82 |
parent 8263 | 41031699550a |
child 8298 | 9542f4c3fa1b |
permissions | -rw-r--r-- |
8229
ddf3d6656e7c
config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents:
8222
diff
changeset
|
1 |
# config.py - configuration parsing for Mercurial |
ddf3d6656e7c
config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents:
8222
diff
changeset
|
2 |
# |
ddf3d6656e7c
config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents:
8222
diff
changeset
|
3 |
# Copyright 2009 Matt Mackall <mpm@selenic.com> and others |
ddf3d6656e7c
config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents:
8222
diff
changeset
|
4 |
# |
ddf3d6656e7c
config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents:
8222
diff
changeset
|
5 |
# This software may be used and distributed according to the terms of the |
ddf3d6656e7c
config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents:
8222
diff
changeset
|
6 |
# GNU General Public License version 2, incorporated herein by reference. |
ddf3d6656e7c
config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents:
8222
diff
changeset
|
7 |
|
8144 | 8 |
from i18n import _ |
8183
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
9 |
import re, error, os |
8144 | 10 |
|
11 |
class sortdict(dict): |
|
8184
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
12 |
'a simple sorted dictionary' |
8144 | 13 |
def __init__(self, data=None): |
14 |
self._list = [] |
|
15 |
if data: |
|
16 |
self.update(data) |
|
17 |
def copy(self): |
|
18 |
return sortdict(self) |
|
19 |
def __setitem__(self, key, val): |
|
20 |
if key in self: |
|
21 |
self._list.remove(key) |
|
22 |
self._list.append(key) |
|
23 |
dict.__setitem__(self, key, val) |
|
24 |
def __iter__(self): |
|
25 |
return self._list.__iter__() |
|
26 |
def update(self, src): |
|
27 |
for k in src: |
|
28 |
self[k] = src[k] |
|
29 |
def items(self): |
|
8222
d30a21594812
more whitespace cleanup and some other style nits
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
8198
diff
changeset
|
30 |
return [(k, self[k]) for k in self._list] |
8184
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
31 |
def __delitem__(self, key): |
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
32 |
dict.__delitem__(self, key) |
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
33 |
self._list.remove(key) |
8144 | 34 |
|
8186
6a0018cdb2fe
config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents:
8185
diff
changeset
|
35 |
class config(object): |
8144 | 36 |
def __init__(self, data=None): |
37 |
self._data = {} |
|
8185
dc10a7a3f1d4
config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents:
8184
diff
changeset
|
38 |
self._source = {} |
8144 | 39 |
if data: |
40 |
for k in data._data: |
|
41 |
self._data[k] = data[k].copy() |
|
8185
dc10a7a3f1d4
config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents:
8184
diff
changeset
|
42 |
self._source = data._source.copy() |
8144 | 43 |
def copy(self): |
44 |
return config(self) |
|
45 |
def __contains__(self, section): |
|
46 |
return section in self._data |
|
8186
6a0018cdb2fe
config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents:
8185
diff
changeset
|
47 |
def __getitem__(self, section): |
6a0018cdb2fe
config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents:
8185
diff
changeset
|
48 |
return self._data.get(section, {}) |
6a0018cdb2fe
config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents:
8185
diff
changeset
|
49 |
def __iter__(self): |
6a0018cdb2fe
config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents:
8185
diff
changeset
|
50 |
for d in self.sections(): |
6a0018cdb2fe
config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents:
8185
diff
changeset
|
51 |
yield d |
8193
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
52 |
def update(self, src): |
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
53 |
for s in src: |
8144 | 54 |
if s not in self: |
55 |
self._data[s] = sortdict() |
|
8193
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
56 |
self._data[s].update(src._data[s]) |
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
57 |
self._source.update(src._source) |
8144 | 58 |
def get(self, section, item, default=None): |
8185
dc10a7a3f1d4
config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents:
8184
diff
changeset
|
59 |
return self._data.get(section, {}).get(item, default) |
8198
cf9accffd0b3
config: getsource -> source
Matt Mackall <mpm@selenic.com>
parents:
8193
diff
changeset
|
60 |
def source(self, section, item): |
8185
dc10a7a3f1d4
config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents:
8184
diff
changeset
|
61 |
return self._source.get((section, item), "") |
8144 | 62 |
def sections(self): |
63 |
return sorted(self._data.keys()) |
|
64 |
def items(self, section): |
|
8185
dc10a7a3f1d4
config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents:
8184
diff
changeset
|
65 |
return self._data.get(section, {}).items() |
8144 | 66 |
def set(self, section, item, value, source=""): |
67 |
if section not in self: |
|
68 |
self._data[section] = sortdict() |
|
8185
dc10a7a3f1d4
config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents:
8184
diff
changeset
|
69 |
self._data[section][item] = value |
dc10a7a3f1d4
config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents:
8184
diff
changeset
|
70 |
self._source[(section, item)] = source |
8144 | 71 |
|
8265
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
72 |
def parse(self, src, data, sections=None, remap=None, include=None): |
8144 | 73 |
sectionre = re.compile(r'\[([^\[]+)\]') |
8263
41031699550a
config: allow spaces in key portion of items
Matt Mackall <mpm@selenic.com>
parents:
8229
diff
changeset
|
74 |
itemre = re.compile(r'([^=\s][^=]*?)\s*=\s*(.*\S|)') |
8192
5fd8e60a935d
config: deal with spaces at end of line more carefully
Matt Mackall <mpm@selenic.com>
parents:
8187
diff
changeset
|
75 |
contre = re.compile(r'\s+(\S.*\S)') |
8144 | 76 |
emptyre = re.compile(r'(;|#|\s*$)') |
8192
5fd8e60a935d
config: deal with spaces at end of line more carefully
Matt Mackall <mpm@selenic.com>
parents:
8187
diff
changeset
|
77 |
unsetre = re.compile(r'%unset\s+(\S+)') |
5fd8e60a935d
config: deal with spaces at end of line more carefully
Matt Mackall <mpm@selenic.com>
parents:
8187
diff
changeset
|
78 |
includere = re.compile(r'%include\s+(\S.*\S)') |
8144 | 79 |
section = "" |
80 |
item = None |
|
81 |
line = 0 |
|
82 |
cont = 0 |
|
8180 | 83 |
|
8265
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
84 |
for l in data.splitlines(1): |
8144 | 85 |
line += 1 |
86 |
if cont: |
|
87 |
m = contre.match(l) |
|
88 |
if m: |
|
8193
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
89 |
if sections and section not in sections: |
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
90 |
continue |
8144 | 91 |
v = self.get(section, item) + "\n" + m.group(1) |
8265
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
92 |
self.set(section, item, v, "%s:%d" % (src, line)) |
8144 | 93 |
continue |
94 |
item = None |
|
8183
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
95 |
m = includere.match(l) |
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
96 |
if m: |
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
97 |
inc = m.group(1) |
8265
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
98 |
base = os.path.dirname(src) |
8183
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
99 |
inc = os.path.normpath(os.path.join(base, inc)) |
8265
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
100 |
if include: |
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
101 |
include(inc, remap=remap, sections=sections) |
8183
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
102 |
continue |
8144 | 103 |
if emptyre.match(l): |
104 |
continue |
|
105 |
m = sectionre.match(l) |
|
106 |
if m: |
|
107 |
section = m.group(1) |
|
108 |
if section not in self: |
|
109 |
self._data[section] = sortdict() |
|
110 |
continue |
|
111 |
m = itemre.match(l) |
|
112 |
if m: |
|
113 |
item = m.group(1) |
|
8193
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
114 |
cont = 1 |
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
115 |
if sections and section not in sections: |
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
116 |
continue |
8265
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
117 |
self.set(section, item, m.group(2), "%s:%d" % (src, line)) |
8144 | 118 |
continue |
8184
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
119 |
m = unsetre.match(l) |
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
120 |
if m: |
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
121 |
name = m.group(1) |
8193
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
122 |
if sections and section not in sections: |
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
123 |
continue |
8184
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
124 |
if self.get(section, name) != None: |
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
125 |
del self._data[section][name] |
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
126 |
continue |
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
127 |
|
8144 | 128 |
raise error.ConfigError(_('config error at %s:%d: \'%s\'') |
8265
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
129 |
% (src, line, l.rstrip())) |
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
130 |
|
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
131 |
def read(self, path, fp=None, sections=None, remap=None): |
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
132 |
if not fp: |
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
133 |
fp = open(path) |
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
134 |
self.parse(path, fp.read(), sections, remap, self.read) |