diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py index 0d13cdf9f3..6804291208 100644 --- a/pywikibot/__init__.py +++ b/pywikibot/__init__.py @@ -41,21 +41,24 @@ CaptchaError, SpamfilterError, CircularRedirect, WikiBaseError, CoordinateGlobeUnknownException, ) -from pywikibot.textlib import ( - unescape, replaceExcept, removeDisabledParts, removeHTMLParts, - isDisabled, interwikiFormat, interwikiSort, - getLanguageLinks, replaceLanguageLinks, - removeLanguageLinks, removeLanguageLinksAndSeparator, - getCategoryLinks, categoryFormat, replaceCategoryLinks, - removeCategoryLinks, removeCategoryLinksAndSeparator, - replaceCategoryInPlace, compileLinkR, extract_templates_and_params, -) -from pywikibot.tools import UnicodeMixin, deprecated, deprecate_arg +from pywikibot.tools import UnicodeMixin, redirect_func from pywikibot.i18n import translate from pywikibot.data.api import UploadWarning +import pywikibot.textlib as textlib +import pywikibot.tools + +textlib_methods = ( + 'unescape', 'replaceExcept', 'removeDisabledParts', 'removeHTMLParts', + 'isDisabled', 'interwikiFormat', 'interwikiSort', + 'getLanguageLinks', 'replaceLanguageLinks', + 'removeLanguageLinks', 'removeLanguageLinksAndSeparator', + 'getCategoryLinks', 'categoryFormat', 'replaceCategoryLinks', + 'removeCategoryLinks', 'removeCategoryLinksAndSeparator', + 'replaceCategoryInPlace', 'compileLinkR', 'extract_templates_and_params', +) __all__ = ( - 'config', 'ui', 'UnicodeMixin', 'translate', 'deprecated', 'deprecate_arg', + 'config', 'ui', 'UnicodeMixin', 'translate', 'Page', 'FilePage', 'ImagePage', 'Category', 'Link', 'User', 'ItemPage', 'PropertyPage', 'Claim', 'TimeStripper', 'html2unicode', 'url2unicode', 'unicode2html', @@ -67,17 +70,24 @@ 'PageRelatedError', 'IsRedirectPage', 'IsNotRedirectPage', 'PageNotSaved', 'UploadWarning', 'LockedPage', 'EditConflict', 'ServerError', 'FatalServerError', 'Server504Error', - 'CaptchaError', 'SpamfilterError', 'CircularRedirect', + 'CaptchaError', 'SpamfilterError', 'CircularRedirect', 'WikiBaseError', 'CoordinateGlobeUnknownException', - 'unescape', 'replaceExcept', 'removeDisabledParts', 'removeHTMLParts', - 'isDisabled', 'interwikiFormat', 'interwikiSort', - 'getLanguageLinks', 'replaceLanguageLinks', - 'removeLanguageLinks', 'removeLanguageLinksAndSeparator', - 'getCategoryLinks', 'categoryFormat', 'replaceCategoryLinks', - 'removeCategoryLinks', 'removeCategoryLinksAndSeparator', - 'replaceCategoryInPlace', 'compileLinkR', 'extract_templates_and_params', 'QuitKeyboardInterrupt', ) +# flake8 is unable to detect concatenation in the same operation +# like: +# ) + textlib_methods +# so instead use this trick +globals()['__all__'] = __all__ + textlib_methods + +for _name in textlib_methods: + target = getattr(textlib, _name) + wrapped_func = redirect_func(target) + globals()[_name] = wrapped_func + + +deprecated = redirect_func(pywikibot.tools.deprecated) +deprecate_arg = redirect_func(pywikibot.tools.deprecate_arg) class Timestamp(datetime.datetime): @@ -491,7 +501,7 @@ def Site(code=None, fam=None, user=None, sysop=None, interface=None): link_regex = re.compile(r'\[\[(?P[^\]|[<>{}]*)(\|.*?)?\]\]') -@deprecated("comment parameter for page saving method") +@pywikibot.tools.deprecated("comment parameter for page saving method") def setAction(s): """Set a summary to use for changed page submissions""" config.default_edit_summary = s diff --git a/pywikibot/tools.py b/pywikibot/tools.py index 462b5ef8b4..fb8628f682 100644 --- a/pywikibot/tools.py +++ b/pywikibot/tools.py @@ -314,6 +314,55 @@ def wrapper(*__args, **__kw): return decorator +def redirect_func(target, source_module=None, target_module=None): + """ + Return a function which can be used to redirect to 'target'. + + It also acts like marking that function deprecated and copies all + parameters. + + @param target: The targeted function which is to be executed. + @type target: callable + @param source_module: The module of the old function. If '.' defaults + to target_module. If 'None' (default) it tries to guess it from the + executing function. + @type source_module: basestring + @param target_module: The module of the target function. If + 'None' (default) it tries to get it from the target. Might not work + with nested classes. + @type target_module: basestring + @return: A new function which adds a warning prior to each execution. + @rtype: callable + """ + class Wrapper(object): + def __init__(self, function, source, target): + self._function = function + self.parameters = {'new': function.func_name, + 'target': target, + 'source': source} + self.warning = ('{source}{new} is DEPRECATED, use {target}{new} ' + 'instead.').format(**self.parameters) + + def call(self, *a, **kw): + warning(self.warning) + return self._function(*a, **kw) + + if target_module is None: + target_module = target.__module__ + if hasattr(target, 'im_class'): + target_module += '.' + target.im_class.__name__ + if target_module and target_module[-1] != '.': + target_module += '.' + if source_module is '.': + source_module = target_module + elif source_module and source_module[-1] != '.': + source_module += '.' + else: + source_module = (sys._getframe(1).f_code.co_filename.rsplit("/", 1)[0] + .replace("/", ".") + ".") + return Wrapper(target, source_module, target_module).call + + if __name__ == "__main__": def _test(): import doctest