Merge lp:~max-rabkin/ibid/config-dflt-336627 into lp:~ibid-core/ibid/old-trunk-1.6

Proposed by Max Rabkin
Status: Superseded
Proposed branch: lp:~max-rabkin/ibid/config-dflt-336627
Merge into: lp:~ibid-core/ibid/old-trunk-1.6
Diff against target: 133 lines (+79/-14)
1 file modified
ibid/plugins/admin.py (+79/-14)
To merge this branch: bzr merge lp:~max-rabkin/ibid/config-dflt-336627
Reviewer Review Type Date Requested Status
Jonathan Hitchcock Approve
Stefano Rivera Approve
Review via email: mp+52319@code.launchpad.net

This proposal has been superseded by a proposal from 2011-06-21.

Commit message

Display the default value when unset config options are queried

To post a comment you must log in.
Revision history for this message
Stefano Rivera (stefanor) wrote :

find_option's docstring should be clearer that only plugins / sources are supported, and then only the Options themselves, not data within nested dicts.

. in a regex needs to be escaped

> for thing in things

Meh I hate that. I'd be tempted to use plugin and plugins. Sources are also plugins, in the general sense.

Query: get config plugins.core
Response: Keys: names and ignore
Query: get config plugins.core.limit_time
Response: 10

limit_time is query-able, but not listed.

Query: get config sources.atrum.delay_factor
Response: No such option

Something's not quite right

review: Needs Fixing
1018. By Max Rabkin

Clarify scope of find_option

1019. By Max Rabkin

Allow sub-options

1020. By Max Rabkin

Support partial option keys

Revision history for this message
Max Rabkin (max-rabkin) wrote :

> find_option's docstring should be clearer that only plugins / sources are supported,

Done in r1018

> and then only the Options themselves, not data within nested dicts.

Fixed in r1019

> limit_time is query-able, but not listed.

Fixed in r1020

> Query: get config sources.atrum.delay_factor
> Response: No such option

We can't find options in sources or plugins that aren't loaded.

Revision history for this message
Stefano Rivera (stefanor) wrote :

Line 40 looks like it's missing a \ before a . (although I don't think it'll make any practical difference)

Otherwise LGTM

1021. By Max Rabkin

Escape dot separator

1022. By Max Rabkin

Behave nicely for "get config plugins"

1023. By Max Rabkin

cleanup

Revision history for this message
Stefano Rivera (stefanor) :
review: Approve
Revision history for this message
Jonathan Hitchcock (vhata) :
review: Approve

Unmerged revisions

1023. By Max Rabkin

cleanup

1022. By Max Rabkin

Behave nicely for "get config plugins"

1021. By Max Rabkin

Escape dot separator

1020. By Max Rabkin

Support partial option keys

1019. By Max Rabkin

Allow sub-options

1018. By Max Rabkin

Clarify scope of find_option

1017. By Max Rabkin

Factor out find_option

1016. By Max Rabkin

Read defaults for config get

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ibid/plugins/admin.py'
2--- ibid/plugins/admin.py 2010-04-13 10:06:03 +0000
3+++ ibid/plugins/admin.py 2011-06-19 12:29:29 +0000
4@@ -1,13 +1,15 @@
5 # Copyright (c) 2008-2010, Michael Gorven
6 # Released under terms of the MIT/X/Expat Licence. See COPYING for details.
7
8+import logging
9 from os.path import join
10+import re
11+
12 from twisted.internet import reactor
13-import logging
14
15 import ibid
16 from ibid.utils import human_join
17-from ibid.config import FileConfig
18+from ibid.config import FileConfig, Option
19 from ibid.plugins import Processor, match, authorise, auth_responses
20 from ibid.utils import ibid_version
21
22@@ -19,18 +21,19 @@
23 'description': u'Lists, loads and unloads plugins.',
24 'categories': ('admin',),
25 }
26-class ListPLugins(Processor):
27+class ListPlugins(Processor):
28 usage = u'list plugins'
29 features = ('plugins',)
30
31 @match(r'lsmod|list plugins')
32 def handler(self, event):
33- plugins = []
34- for processor in ibid.processors:
35- if processor.name not in plugins:
36- plugins.append(processor.name)
37+ event.addresponse(u'Plugins: %s', human_join(sorted(list_plugins())) or u'none')
38
39- event.addresponse(u'Plugins: %s', human_join(sorted(plugins)) or u'none')
40+def list_plugins():
41+ plugins = set()
42+ for processor in ibid.processors:
43+ plugins.add(processor.name)
44+ return sorted(plugins)
45
46 features['core'] = {
47 'description': u'Reloads core modules.',
48@@ -211,17 +214,79 @@
49
50 event.addresponse(True)
51
52+ def find_option(self, key):
53+ """
54+ Find the Option object(s) for a config key in a plugin or source.
55+
56+ Returns None if the key does not correspond to an Option object.
57+
58+ Returns a dictionary mapping option names to (option, object) pairs as
59+ below, if key is of the form plugins.pluginname or sources.sourcename.
60+
61+ Otherwise, returns (option, object, key_tail) where option is an
62+ Option instance, and object is either a Processor or Source object
63+ through which the option is accessed, and key_tail is the part of
64+ the key which names a sub-option of this option (or a blank string).
65+ """
66+ m = re.match(r'^(plugins|sources)\.([^.]+)(?:\.([^.]+)(?:\.(.+))?)?$', key)
67+ if m is None:
68+ return None
69+
70+ kind, plugin, name, key_tail = m.groups()
71+ if kind == 'sources':
72+ if plugin in ibid.sources:
73+ things = [ibid.sources[plugin]]
74+ else:
75+ return None
76+ else:
77+ things = [p for p in ibid.processors if p.name == plugin]
78+
79+ if name is None:
80+ mapping = {}
81+ else:
82+ mapping = None
83+
84+ for thing in things:
85+ options = thing.__dict__.values() + \
86+ type(thing).__dict__.values()
87+ for option in options:
88+ if isinstance(option, Option):
89+ if name is None:
90+ mapping[option.name] = (option, thing)
91+ elif option.name == name:
92+ return option, thing, key_tail or u''
93+ return mapping
94+
95 @match(r'(?:get config|config get) (\S+?)')
96 def get(self, event, key):
97 if 'password' in key.lower() and not auth_responses(event, u'config'):
98 return
99
100- config = ibid.config
101- for part in key.split('.'):
102- if not isinstance(config, dict) or part not in config:
103- event.addresponse(u'No such option')
104- return
105- config = config[part]
106+ option = self.find_option(key)
107+ if isinstance(option, dict):
108+ config = option
109+ key = ''
110+ elif option is not None:
111+ config = option[0].__get__(option[1], type(option[1]))
112+ key = option[2]
113+ elif key == 'plugins':
114+ # Construct a dictionary since this isn't a list-valued option,
115+ # but a list of option keys.
116+ config = dict((plugin, None) for plugin in list_plugins())
117+ key = ''
118+ elif key == 'sources':
119+ config = ibid.sources
120+ key = ''
121+ else:
122+ config = ibid.config
123+
124+ if key:
125+ for part in key.split('.'):
126+ if not isinstance(config, dict) or part not in config:
127+ event.addresponse(u'No such option')
128+ return
129+ config = config[part]
130+
131 if isinstance(config, list):
132 event.addresponse(u', '.join(config))
133 elif isinstance(config, dict):

Subscribers

People subscribed via source and target branches