Enhance plugin config with attribute accessors.
This makes updating the config after plugin initialization much easier.
This commit is contained in:
parent
35396d2977
commit
a06fa2de67
16 changed files with 154 additions and 86 deletions
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
|
||||
if not self.local_time:
|
||||
def default_local_time(jid):
|
||||
return xep_0082.datetime(offset=self.tz_offset)
|
||||
|
||||
if not self.local_time:
|
||||
self.local_time = default_local_time
|
||||
|
||||
self.xmpp.registerHandler(
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue