Skip to content

Commit

Permalink
[FEAT] Add deprecation warnings for textlib/deprecation redirects
Browse files Browse the repository at this point in the history
It's adding a function which dynamically can create a redirect to
another function and warn because of deprecation when the
redirected function is executed. It works similar to the
@deprecated decorator but doesn't require the old function.

All functions which from 'textlib' which were simply redirected
from 'pywikibot' to the 'textlib' module are created with this
function. Also 'deprecated' and 'deprecate_arg' are marked as
deprecated too.

Change-Id: I69dbf351c22fd0caacbf047ae38aca067f8cef96
  • Loading branch information
xZise committed Aug 23, 2014
1 parent 88b2d33 commit 5426720
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 20 deletions.
50 changes: 30 additions & 20 deletions pywikibot/__init__.py
Expand Up @@ -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',
Expand All @@ -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):
Expand Down Expand Up @@ -491,7 +501,7 @@ def Site(code=None, fam=None, user=None, sysop=None, interface=None):
link_regex = re.compile(r'\[\[(?P<title>[^\]|[<>{}]*)(\|.*?)?\]\]')


@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
Expand Down
49 changes: 49 additions & 0 deletions pywikibot/tools.py
Expand Up @@ -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
Expand Down

0 comments on commit 5426720

Please sign in to comment.