Enhance plugin config with attribute accessors.

This makes updating the config after plugin initialization much easier.
This commit is contained in:
Lance Stout 2012-07-26 23:04:16 -07:00
parent 35396d2977
commit a06fa2de67
16 changed files with 154 additions and 86 deletions

View file

@ -29,10 +29,13 @@ class FeatureMechanisms(BasePlugin):
description = 'RFC 6120: Stream Feature: SASL'
dependencies = set()
stanza = stanza
default_config = {
'use_mech': None,
'sasl_callback': None,
'order': 100
}
def plugin_init(self):
self.use_mech = self.config.get('use_mech', None)
if not self.use_mech and not self.xmpp.boundjid.user:
self.use_mech = 'ANONYMOUS'
@ -53,15 +56,14 @@ class FeatureMechanisms(BasePlugin):
values[value] = creds[value]
mech.fulfill(values)
sasl_callback = self.config.get('sasl_callback', None)
if sasl_callback is None:
sasl_callback = basic_callback
if self.sasl_callback is None:
self.sasl_callback = basic_callback
self.mech = None
self.sasl = suelta.SASL(self.xmpp.boundjid.domain, 'xmpp',
username=self.xmpp.boundjid.user,
sec_query=suelta.sec_query_allow,
request_values=sasl_callback,
request_values=self.sasl_callback,
tls_active=tls_active,
mech=self.use_mech)
@ -95,7 +97,7 @@ class FeatureMechanisms(BasePlugin):
self.xmpp.register_feature('mechanisms',
self._handle_sasl_auth,
restart=True,
order=self.config.get('order', 100))
order=self.order)
def _handle_sasl_auth(self, features):
"""

View file

@ -14,6 +14,7 @@
"""
import sys
import copy
import logging
import threading
@ -272,6 +273,14 @@ class BasePlugin(object):
#: be initialized as needed if this plugin is enabled.
dependencies = set()
#: The basic, standard configuration for the plugin, which may
#: be overridden when initializing the plugin. The configuration
#: fields included here may be accessed directly as attributes of
#: the plugin. For example, including the configuration field 'foo'
#: would mean accessing `plugin.foo` returns the current value of
#: `plugin.config['foo']`.
default_config = {}
def __init__(self, xmpp, config=None):
self.xmpp = xmpp
if self.xmpp:
@ -279,7 +288,32 @@ class BasePlugin(object):
#: A plugin's behaviour may be configurable, in which case those
#: configuration settings will be provided as a dictionary.
self.config = config if config is not None else {}
self.config = copy.copy(self.default_config)
if config:
self.config.update(config)
def __getattr__(self, key):
"""Provide direct access to configuration fields.
If the standard configuration includes the option `'foo'`, then
accessing `self.foo` should be the same as `self.config['foo']`.
"""
if key in self.default_config:
return self.config.get(key, None)
else:
return object.__getattribute__(self, key)
def __setattr__(self, key, value):
"""Provide direct assignment to configuration fields.
If the standard configuration includes the option `'foo'`, then
assigning to `self.foo` should be the same as assigning to
`self.config['foo']`.
"""
if key in self.default_config:
self.config[key] = value
else:
super(BasePlugin, self).__setattr__(key, value)
def _init(self):
"""Initialize plugin state, such as registering event handlers.

View file

@ -40,14 +40,15 @@ class XEP_0027(BasePlugin):
description = 'XEP-0027: Current Jabber OpenPGP Usage'
dependencies = set()
stanza = stanza
default_config = {
'gpg_binary': 'gpg',
'gpg_home': '',
'use_agent': True,
'keyring': None,
'key_server': 'pgp.mit.edu'
}
def plugin_init(self):
self.gpg_binary = self.config.get('gpg_binary', 'gpg')
self.gpg_home = self.config.get('gpg_home', '')
self.use_agent = self.config.get('use_agent', True)
self.keyring = self.config.get('keyring', None)
self.key_server = self.config.get('key_server', 'pgp.mit.edu')
self.gpg = GPG(gnupghome=self.gpg_home,
gpgbinary=self.gpg_binary,
use_agent=self.use_agent,

View file

@ -88,6 +88,10 @@ class XEP_0030(BasePlugin):
description = 'XEP-0030: Service Discovery'
dependencies = set()
stanza = stanza
default_config = {
'use_cache': True,
'wrap_results': False
}
def plugin_init(self):
"""
@ -108,9 +112,6 @@ class XEP_0030(BasePlugin):
self.static = StaticDisco(self.xmpp, self)
self.use_cache = self.config.get('use_cache', True)
self.wrap_results = self.config.get('wrap_results', False)
self._disco_ops = [
'get_info', 'set_info', 'set_identities', 'set_features',
'get_items', 'set_items', 'del_items', 'add_identity',

View file

@ -20,18 +20,19 @@ class XEP_0047(BasePlugin):
description = 'XEP-0047: In-band Bytestreams'
dependencies = set(['xep_0030'])
stanza = stanza
default_config = {
'max_block_size': 8192,
'window_size': 1,
'auto_accept': True,
'accept_stream': None
}
def plugin_init(self):
self.streams = {}
self.pending_streams = {3: 5}
self.pending_streams = {}
self.pending_close_streams = {}
self._stream_lock = threading.Lock()
self.max_block_size = self.config.get('max_block_size', 8192)
self.window_size = self.config.get('window_size', 1)
self.auto_accept = self.config.get('auto_accept', True)
self.accept_stream = self.config.get('accept_stream', None)
register_stanza_plugin(Iq, Open)
register_stanza_plugin(Iq, Close)
register_stanza_plugin(Iq, Data)

View file

@ -82,12 +82,18 @@ class XEP_0050(BasePlugin):
description = 'XEP-0050: Ad-Hoc Commands'
dependencies = set(['xep_0030', 'xep_0004'])
stanza = stanza
default_config = {
'threaded': True,
'session_db': None
}
def plugin_init(self):
"""Start the XEP-0050 plugin."""
self.threaded = self.config.get('threaded', True)
self.sessions = self.session_db
if self.sessions is None:
self.sessions = {}
self.commands = {}
self.sessions = self.config.get('session_db', {})
self.xmpp.register_handler(
Callback("Ad-Hoc Execute",

View file

@ -27,10 +27,12 @@ class XEP_0077(BasePlugin):
description = 'XEP-0077: In-Band Registration'
dependencies = set(['xep_0004', 'xep_0066'])
stanza = stanza
default_config = {
'create_account': True,
'order': 50
}
def plugin_init(self):
self.create_account = self.config.get('create_account', True)
register_stanza_plugin(StreamFeatures, RegisterFeature)
register_stanza_plugin(Iq, Register)
@ -38,14 +40,14 @@ class XEP_0077(BasePlugin):
self.xmpp.register_feature('register',
self._handle_register_feature,
restart=False,
order=self.config.get('order', 50))
order=self.order)
register_stanza_plugin(Register, self.xmpp['xep_0004'].stanza.Form)
register_stanza_plugin(Register, self.xmpp['xep_0066'].stanza.OOB)
def plugin_end(self):
if not self.xmpp.is_component:
self.xmpp.unregister_feature('register', self.config.get('order', 50))
self.xmpp.unregister_feature('register', self.order)
def _handle_register_feature(self, features):
if 'mechanisms' in self.xmpp.features:

View file

@ -34,18 +34,21 @@ class XEP_0078(BasePlugin):
description = 'XEP-0078: Non-SASL Authentication'
dependencies = set()
stanza = stanza
default_config = {
'order': 15
}
def plugin_init(self):
self.xmpp.register_feature('auth',
self._handle_auth,
restart=False,
order=self.config.get('order', 15))
order=self.order)
register_stanza_plugin(Iq, stanza.IqAuth)
register_stanza_plugin(StreamFeatures, stanza.AuthFeature)
def plugin_end(self):
self.xmpp.unregister_feature('auth', self.config.get('order', 15))
self.xmpp.unregister_feature('auth', self.order)
def _handle_auth(self, features):
# If we can or have already authenticated with SASL, do nothing.

View file

@ -37,7 +37,10 @@ class XEP_0086(BasePlugin):
description = 'XEP-0086: Error Condition Mappings'
dependencies = set()
stanza = stanza
default_config = {
'override': True
}
def plugin_init(self):
register_stanza_plugin(Error, LegacyError,
overrides=self.config.get('override', True))
overrides=self.override)

View file

@ -30,16 +30,18 @@ class XEP_0092(BasePlugin):
description = 'XEP-0092: Software Version'
dependencies = set(['xep_0030'])
stanza = stanza
default_config = {
'software_name': 'SleekXMPP',
'version': sleekxmpp.__version__,
'os': ''
}
def plugin_init(self):
"""
Start the XEP-0092 plugin.
"""
self.name = self.config.get('name', 'SleekXMPP')
self.version = self.config.get('version', sleekxmpp.__version__)
self.os = self.config.get('os', '')
self.getVersion = self.get_version
if 'name' in self.config:
self.software_name = self.config['name']
self.xmpp.register_handler(
Callback('Software Version',
@ -63,7 +65,7 @@ class XEP_0092(BasePlugin):
iq -- The Iq stanza containing the software version query.
"""
iq.reply()
iq['software_version']['name'] = self.name
iq['software_version']['name'] = self.software_name
iq['software_version']['version'] = self.version
iq['software_version']['os'] = self.os
iq.send()
@ -88,3 +90,6 @@ class XEP_0092(BasePlugin):
del values['lang']
return values
return False
XEP_0092.getVersion = XEP_0092.get_version

View file

@ -33,16 +33,17 @@ class XEP_0115(BasePlugin):
description = 'XEP-0115: Entity Capabilities'
dependencies = set(['xep_0030', 'xep_0128', 'xep_0004'])
stanza = stanza
default_config = {
'hash': 'sha-1',
'caps_node': None,
'broadcast': True
}
def plugin_init(self):
self.hashes = {'sha-1': hashlib.sha1,
'sha1': hashlib.sha1,
'md5': hashlib.md5}
self.hash = self.config.get('hash', 'sha-1')
self.caps_node = self.config.get('caps_node', None)
self.broadcast = self.config.get('broadcast', True)
if self.caps_node is None:
ver = sleekxmpp.__version__
self.caps_node = 'http://sleekxmpp.com/ver/%s' % ver

View file

@ -26,13 +26,14 @@ class XEP_0184(BasePlugin):
description = 'XEP-0184: Message Delivery Receipts'
dependencies = set(['xep_0030'])
stanza = stanza
default_config = {
'auto_ack': True,
'auto_request': False
}
ack_types = ('normal', 'chat', 'headline')
def plugin_init(self):
self.auto_ack = self.config.get('auto_ack', True)
self.auto_request = self.config.get('auto_request', False)
register_stanza_plugin(Message, Request)
register_stanza_plugin(Message, Received)

View file

@ -34,6 +34,32 @@ class XEP_0198(BasePlugin):
description = 'XEP-0198: Stream Management'
dependencies = set()
stanza = stanza
default_config = {
#: The last ack number received from the server.
'last_ack': 0,
#: The number of stanzas to wait between sending ack requests to
#: the server. Setting this to ``1`` will send an ack request after
#: every sent stanza. Defaults to ``5``.
'window': 5,
#: The stream management ID for the stream. Knowing this value is
#: required in order to do stream resumption.
'sm_id': None,
#: A counter of handled incoming stanzas, mod 2^32.
'handled': 0,
#: A counter of unacked outgoing stanzas, mod 2^32.
'seq': 0,
#: Control whether or not the ability to resume the stream will be
#: requested when enabling stream management. Defaults to ``True``.
'allow_resume': True,
'order': 10100,
'resume_order': 9000
}
def plugin_init(self):
"""Start the XEP-0198 plugin."""
@ -43,30 +69,9 @@ class XEP_0198(BasePlugin):
if self.xmpp.is_component:
return
#: The stream management ID for the stream. Knowing this value is
#: required in order to do stream resumption.
self.sm_id = self.config.get('sm_id', None)
#: A counter of handled incoming stanzas, mod 2^32.
self.handled = self.config.get('handled', 0)
#: A counter of unacked outgoing stanzas, mod 2^32.
self.seq = self.config.get('seq', 0)
#: The last ack number received from the server.
self.last_ack = self.config.get('last_ack', 0)
#: The number of stanzas to wait between sending ack requests to
#: the server. Setting this to ``1`` will send an ack request after
#: every sent stanza. Defaults to ``5``.
self.window = self.config.get('window', 5)
self.window_counter = self.window
self.window_counter_lock = threading.Lock()
#: Control whether or not the ability to resume the stream will be
#: requested when enabling stream management. Defaults to ``True``.
self.allow_resume = self.config.get('allow_resume', True)
self.enabled = threading.Event()
self.unacked_queue = collections.deque()
@ -92,11 +97,11 @@ class XEP_0198(BasePlugin):
self.xmpp.register_feature('sm',
self._handle_sm_feature,
restart=True,
order=self.config.get('order', 10100))
order=self.order)
self.xmpp.register_feature('sm',
self._handle_sm_feature,
restart=True,
order=self.config.get('resume_order', 9000))
order=self.resume_order)
self.xmpp.register_handler(
Callback('Stream Management Enabled',
@ -137,8 +142,8 @@ class XEP_0198(BasePlugin):
if self.xmpp.is_component:
return
self.xmpp.unregister_feature('sm', self.config.get('order', 10100))
self.xmpp.unregister_feature('sm', self.config.get('resume_order', 9000))
self.xmpp.unregister_feature('sm', self.order)
self.xmpp.unregister_feature('sm', self.resume_order)
self.xmpp.del_event_handler('session_end', self.session_end)
self.xmpp.del_filter('in', self._handle_incoming)
self.xmpp.del_filter('out_sync', self._handle_outgoing)

View file

@ -51,15 +51,16 @@ class XEP_0199(BasePlugin):
description = 'XEP-0199: XMPP Ping'
dependencies = set(['xep_0030'])
stanza = stanza
default_config = {
'keepalive': False,
'frequency': 300,
'timeout': 30
}
def plugin_init(self):
"""
Start the XEP-0199 plugin.
"""
self.keepalive = self.config.get('keepalive', False)
self.frequency = float(self.config.get('frequency', 300))
self.timeout = self.config.get('timeout', 30)
register_stanza_plugin(Iq, Ping)
self.xmpp.register_handler(

View file

@ -30,21 +30,22 @@ class XEP_0202(BasePlugin):
description = 'XEP-0202: Entity Time'
dependencies = set(['xep_0030', 'xep_0082'])
stanza = stanza
default_config = {
#: As a default, respond to time requests with the
#: local time returned by XEP-0082. However, a
#: custom function can be supplied which accepts
#: the JID of the entity to query for the time.
'local_time': None,
'tz_offset': 0
}
def plugin_init(self):
"""Start the XEP-0203 plugin."""
self.tz_offset = self.config.get('tz_offset', 0)
# As a default, respond to time requests with the
# local time returned by XEP-0082. However, a
# custom function can be supplied which accepts
# the JID of the entity to query for the time.
self.local_time = self.config.get('local_time', None)
def default_local_time(jid):
return xep_0082.datetime(offset=self.tz_offset)
if not self.local_time:
def default_local_time(jid):
return xep_0082.datetime(offset=self.tz_offset)
self.local_time = default_local_time
self.xmpp.registerHandler(

View file

@ -25,10 +25,11 @@ class XEP_0256(BasePlugin):
description = 'XEP-0256: Last Activity in Presence'
dependencies = set(['xep_0012'])
stanza = stanza
default_config = {
'auto_last_activity': False
}
def plugin_init(self):
self.auto_last_activity = self.config.get('auto_last_activity', False)
register_stanza_plugin(Presence, LastActivity)
self.xmpp.add_filter('out', self._initial_presence_activity)