Show More
@@ -6,6 +6,7 b'' | |||
|
6 | 6 | |
|
7 | 7 | from __future__ import print_function |
|
8 | 8 | |
|
9 | import json | |
|
9 | 10 | import logging |
|
10 | 11 | import os |
|
11 | 12 | import re |
@@ -535,8 +536,17 b' class Application(SingletonConfigurable):' | |||
|
535 | 536 | def load_config_file(self, filename, path=None): |
|
536 | 537 | """Load config files by filename and path.""" |
|
537 | 538 | filename, ext = os.path.splitext(filename) |
|
539 | loaded = [] | |
|
538 | 540 | for config in self._load_config_files(filename, path=path, log=self.log): |
|
541 | loaded.append(config) | |
|
539 | 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 | 552 | def generate_config_file(self): |
@@ -194,6 +194,26 b' class Config(dict):' | |||
|
194 | 194 | |
|
195 | 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 | 217 | def __contains__(self, key): |
|
198 | 218 | # allow nested contains of the form `"Section.key" in config` |
|
199 | 219 | if '.' in key: |
@@ -565,7 +585,7 b' class KeyValueConfigLoader(CommandLineConfigLoader):' | |||
|
565 | 585 | |
|
566 | 586 | |
|
567 | 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 | 589 | uargv = [] |
|
570 | 590 | if enc is None: |
|
571 | 591 | enc = DEFAULT_ENCODING |
@@ -1,28 +1,12 b'' | |||
|
1 | 1 | # encoding: utf-8 |
|
2 | """ | |
|
3 | Tests for IPython.config.loader | |
|
4 | ||
|
5 | Authors: | |
|
6 | ||
|
7 | * Brian Granger | |
|
8 | * Fernando Perez (design help) | |
|
9 | """ | |
|
10 | ||
|
11 | #----------------------------------------------------------------------------- | |
|
12 | # Copyright (C) 2008 The IPython Development Team | |
|
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 | #----------------------------------------------------------------------------- | |
|
2 | """Tests for IPython.config.loader""" | |
|
17 | 3 | |
|
18 | #----------------------------------------------------------------------------- | |
|
19 | # Imports | |
|
20 | #----------------------------------------------------------------------------- | |
|
4 | # Copyright (c) IPython Development Team. | |
|
5 | # Distributed under the terms of the Modified BSD License. | |
|
21 | 6 | |
|
22 | 7 | import os |
|
23 | 8 | import pickle |
|
24 | 9 | import sys |
|
25 | import json | |
|
26 | 10 | |
|
27 | 11 | from tempfile import mkstemp |
|
28 | 12 | from unittest import TestCase |
@@ -43,10 +27,6 b' from IPython.config.loader import (' | |||
|
43 | 27 | ConfigError, |
|
44 | 28 | ) |
|
45 | 29 | |
|
46 | #----------------------------------------------------------------------------- | |
|
47 | # Actual tests | |
|
48 | #----------------------------------------------------------------------------- | |
|
49 | ||
|
50 | 30 | |
|
51 | 31 | pyfile = """ |
|
52 | 32 | c = get_config() |
@@ -118,6 +98,34 b' class TestFileCL(TestCase):' | |||
|
118 | 98 | config = cl.load_config() |
|
119 | 99 | self._check_conf(config) |
|
120 | 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 | }) | |
|
128 | ||
|
121 | 129 | def test_v2raise(self): |
|
122 | 130 | fd, fname = mkstemp('.json') |
|
123 | 131 | f = os.fdopen(fd, 'w') |
General Comments 0
You need to be logged in to leave comments.
Login now