##// END OF EJS Templates
Merge pull request #7082 from minrk/warn-collision...
Matthias Bussonnier -
r19165:ab7cb4b0 merge
parent child Browse files
Show More
@@ -6,6 +6,7 b''
6
6
7 from __future__ import print_function
7 from __future__ import print_function
8
8
9 import json
9 import logging
10 import logging
10 import os
11 import os
11 import re
12 import re
@@ -535,8 +536,17 b' class Application(SingletonConfigurable):'
535 def load_config_file(self, filename, path=None):
536 def load_config_file(self, filename, path=None):
536 """Load config files by filename and path."""
537 """Load config files by filename and path."""
537 filename, ext = os.path.splitext(filename)
538 filename, ext = os.path.splitext(filename)
539 loaded = []
538 for config in self._load_config_files(filename, path=path, log=self.log):
540 for config in self._load_config_files(filename, path=path, log=self.log):
541 loaded.append(config)
539 self.update_config(config)
542 self.update_config(config)
543 if len(loaded) > 1:
544 collisions = loaded[0].collisions(loaded[1])
545 if collisions:
546 self.log.warn("Collisions detected in {0}.py and {0}.json config files."
547 " {0}.json has higher priority: {1}".format(
548 filename, json.dumps(collisions, indent=2),
549 ))
540
550
541
551
542 def generate_config_file(self):
552 def generate_config_file(self):
@@ -193,7 +193,27 b' class Config(dict):'
193 to_update[k] = copy.deepcopy(v)
193 to_update[k] = copy.deepcopy(v)
194
194
195 self.update(to_update)
195 self.update(to_update)
196
196
197 def collisions(self, other):
198 """Check for collisions between two config objects.
199
200 Returns a dict of the form {"Class": {"trait": "collision message"}}`,
201 indicating which values have been ignored.
202
203 An empty dict indicates no collisions.
204 """
205 collisions = {}
206 for section in self:
207 if section not in other:
208 continue
209 mine = self[section]
210 theirs = other[section]
211 for key in mine:
212 if key in theirs and mine[key] != theirs[key]:
213 collisions.setdefault(section, {})
214 collisions[section][key] = "%r ignored, using %r" % (mine[key], theirs[key])
215 return collisions
216
197 def __contains__(self, key):
217 def __contains__(self, key):
198 # allow nested contains of the form `"Section.key" in config`
218 # allow nested contains of the form `"Section.key" in config`
199 if '.' in key:
219 if '.' in key:
@@ -565,7 +585,7 b' class KeyValueConfigLoader(CommandLineConfigLoader):'
565
585
566
586
567 def _decode_argv(self, argv, enc=None):
587 def _decode_argv(self, argv, enc=None):
568 """decode argv if bytes, using stin.encoding, falling back on default enc"""
588 """decode argv if bytes, using stdin.encoding, falling back on default enc"""
569 uargv = []
589 uargv = []
570 if enc is None:
590 if enc is None:
571 enc = DEFAULT_ENCODING
591 enc = DEFAULT_ENCODING
@@ -1,28 +1,12 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """Tests for IPython.config.loader"""
3 Tests for IPython.config.loader
4
5 Authors:
6
7 * Brian Granger
8 * Fernando Perez (design help)
9 """
10
3
11 #-----------------------------------------------------------------------------
4 # Copyright (c) IPython Development Team.
12 # Copyright (C) 2008 The IPython Development Team
5 # Distributed under the terms of the Modified BSD License.
13 #
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
17
18 #-----------------------------------------------------------------------------
19 # Imports
20 #-----------------------------------------------------------------------------
21
6
22 import os
7 import os
23 import pickle
8 import pickle
24 import sys
9 import sys
25 import json
26
10
27 from tempfile import mkstemp
11 from tempfile import mkstemp
28 from unittest import TestCase
12 from unittest import TestCase
@@ -43,10 +27,6 b' from IPython.config.loader import ('
43 ConfigError,
27 ConfigError,
44 )
28 )
45
29
46 #-----------------------------------------------------------------------------
47 # Actual tests
48 #-----------------------------------------------------------------------------
49
50
30
51 pyfile = """
31 pyfile = """
52 c = get_config()
32 c = get_config()
@@ -117,6 +97,34 b' class TestFileCL(TestCase):'
117 cl = JSONFileConfigLoader(fname, log=log)
97 cl = JSONFileConfigLoader(fname, log=log)
118 config = cl.load_config()
98 config = cl.load_config()
119 self._check_conf(config)
99 self._check_conf(config)
100
101 def test_collision(self):
102 a = Config()
103 b = Config()
104 self.assertEqual(a.collisions(b), {})
105 a.A.trait1 = 1
106 b.A.trait2 = 2
107 self.assertEqual(a.collisions(b), {})
108 b.A.trait1 = 1
109 self.assertEqual(a.collisions(b), {})
110 b.A.trait1 = 0
111 self.assertEqual(a.collisions(b), {
112 'A': {
113 'trait1': "1 ignored, using 0",
114 }
115 })
116 self.assertEqual(b.collisions(a), {
117 'A': {
118 'trait1': "0 ignored, using 1",
119 }
120 })
121 a.A.trait2 = 3
122 self.assertEqual(b.collisions(a), {
123 'A': {
124 'trait1': "0 ignored, using 1",
125 'trait2': "2 ignored, using 3",
126 }
127 })
120
128
121 def test_v2raise(self):
129 def test_v2raise(self):
122 fd, fname = mkstemp('.json')
130 fd, fname = mkstemp('.json')
General Comments 0
You need to be logged in to leave comments. Login now