diff --git a/classes.py b/classes.py index d7242df..af4319c 100644 --- a/classes.py +++ b/classes.py @@ -45,7 +45,7 @@ class ChannelState(structures.IRCCaseInsensitiveDict): return self._data[key] -class PyLinkNetworkCore(utils.DeprecatedAttributesObject, utils.CamelCaseToSnakeCase): +class PyLinkNetworkCore(structures.DeprecatedAttributesObject, structures.CamelCaseToSnakeCase): """Base IRC object for PyLink.""" def __init__(self, netname): @@ -1568,7 +1568,7 @@ class Server(): IrcServer = Server -class Channel(utils.DeprecatedAttributesObject, utils.CamelCaseToSnakeCase, structures.CopyWrapper): +class Channel(structures.DeprecatedAttributesObject, structures.CamelCaseToSnakeCase, structures.CopyWrapper): """PyLink IRC channel class.""" def __init__(self, irc, name=None): diff --git a/structures.py b/structures.py index f5314cf..5ab6177 100644 --- a/structures.py +++ b/structures.py @@ -11,6 +11,7 @@ import pickle import os import threading from copy import copy, deepcopy +import string from .log import log from . import conf @@ -151,6 +152,50 @@ class IRCCaseInsensitiveSet(CaseInsensitiveSet): def __copy__(self): return self.__class__(self._irc, data=self._data.copy()) +class DeprecatedAttributesObject(): + """ + Object implementing deprecated attributes and warnings on access. + """ + def __init__(self): + self.deprecated_attributes = {} + + def __getattribute__(self, attr): + # Note: "self.deprecated_attributes" calls this too, so the != check is + # needed to prevent a recursive loop! + # Also ignore reserved names beginning with "__". + if attr != 'deprecated_attributes' and not attr.startswith('__') and attr in self.deprecated_attributes: + log.warning('Attribute %s.%s is deprecated: %s' % (self.__class__.__name__, attr, + self.deprecated_attributes.get(attr))) + + return object.__getattribute__(self, attr) + +class CamelCaseToSnakeCase(): + """ + Class which automatically converts missing attributes from camel case to snake case. + """ + + def __getattr__(self, attr): + """ + Attribute fetching fallback function which normalizes camel case attributes to snake case. + """ + assert isinstance(attr, str), "Requested attribute %r is not a string!" % attr + + normalized_attr = '' # Start off with the first letter, which is ignored when processing + for char in attr: + if char in string.ascii_uppercase: + char = '_' + char.lower() + normalized_attr += char + + classname = self.__class__.__name__ + if normalized_attr == attr: + # __getattr__ only fires if normal attribute fetching fails, so we can assume that + # the attribute was tried already and failed. + raise AttributeError('%s object has no attribute with normalized name %r' % (classname, attr)) + + target = getattr(self, normalized_attr) + log.warning('%s.%s is deprecated, considering migrating to %s.%s!', classname, attr, classname, normalized_attr) + return target + class DataStore: """ Generic database class. Plugins should use a subclass of this such as JSONDataStore or diff --git a/utils.py b/utils.py index c286c37..5837b33 100644 --- a/utils.py +++ b/utils.py @@ -669,47 +669,3 @@ class IRCParser(argparse.ArgumentParser): def exit(self, *args): return - -class DeprecatedAttributesObject(): - """ - Object implementing deprecated attributes and warnings on access. - """ - def __init__(self): - self.deprecated_attributes = {} - - def __getattribute__(self, attr): - # Note: "self.deprecated_attributes" calls this too, so the != check is - # needed to prevent a recursive loop! - # Also ignore reserved names beginning with "__". - if attr != 'deprecated_attributes' and not attr.startswith('__') and attr in self.deprecated_attributes: - log.warning('Attribute %s.%s is deprecated: %s' % (self.__class__.__name__, attr, - self.deprecated_attributes.get(attr))) - - return object.__getattribute__(self, attr) - -class CamelCaseToSnakeCase(): - """ - Class which automatically converts missing attributes from camel case to snake case. - """ - - def __getattr__(self, attr): - """ - Attribute fetching fallback function which normalizes camel case attributes to snake case. - """ - assert isinstance(attr, str), "Requested attribute %r is not a string!" % attr - - normalized_attr = '' # Start off with the first letter, which is ignored when processing - for char in attr: - if char in string.ascii_uppercase: - char = '_' + char.lower() - normalized_attr += char - - classname = self.__class__.__name__ - if normalized_attr == attr: - # __getattr__ only fires if normal attribute fetching fails, so we can assume that - # the attribute was tried already and failed. - raise AttributeError('%s object has no attribute with normalized name %r' % (classname, attr)) - - target = getattr(self, normalized_attr) - log.warning('%s.%s is deprecated, considering migrating to %s.%s!', classname, attr, classname, normalized_attr) - return target