Hello community,
here is the log from the commit of package python-debtcollector for
openSUSE:Factory checked in at 2016-02-17 10:26:10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-debtcollector (Old)
and /work/SRC/openSUSE:Factory/.python-debtcollector.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-debtcollector"
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-debtcollector/python-debtcollector.changes
2015-09-11 09:04:39.000000000 +0200
+++
/work/SRC/openSUSE:Factory/.python-debtcollector.new/python-debtcollector.changes
2016-02-17 12:22:44.000000000 +0100
@@ -1,0 +2,28 @@
+Mon Feb 15 14:12:53 UTC 2016 - [email protected]
+
+- update to 1.3.0:
+ * Updated from global requirements
+ * Add debug testenv in tox
+ * Add updated_kwarg_default_value decorator
+ * Allow replacing a keyword argument
+ * Add 'removed_class' class decorator
+ * py26/py33 are no longer supported by Infra's CI
+ * Add removals.remove note about metaclasses
+ * Updated from global requirements
+ * Update get_class_name from olso.utils
+ * Remove Python 2.6 classifier
+ * Remove python 2.6 and cleanup tox.ini
+ * Add 'moved_read_only_property' descriptor
+ * Add ability to disable warnings being emitted
+ * Add a 'removed_property' descriptor class
+ * No need for Oslo Incubator Sync
+ * docs - Set pbr 'warnerrors' option for doc build
+ * Include changelog/history in docs
+ * tweak language in readme
+ * Enhance the README
+ * Change ignore-errors to ignore_errors
+ * Updated from global requirements
+ * Activate pep8 check that _ is imported
+ * Add a moved function helper
+
+-------------------------------------------------------------------
Old:
----
debtcollector-0.8.0.tar.gz
New:
----
debtcollector-1.3.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-debtcollector.spec ++++++
--- /var/tmp/diff_new_pack.5oLqxg/_old 2016-02-17 12:22:45.000000000 +0100
+++ /var/tmp/diff_new_pack.5oLqxg/_new 2016-02-17 12:22:45.000000000 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-debtcollector
#
-# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -17,17 +17,19 @@
Name: python-debtcollector
-Version: 0.8.0
+Version: 1.3.0
Release: 0
-Summary: A collection of Python deprecation patterns and strategies
that help you collect your technical debt in a non-destructive manner
+Summary: Collection of deprecation patterns that help to collect
technical debt
License: Apache-2.0
Group: Development/Languages/Python
Url: http://www.openstack.org/
Source:
https://pypi.python.org/packages/source/d/debtcollector/debtcollector-%{version}.tar.gz
+BuildRequires: python-Babel
BuildRequires: python-devel
BuildRequires: python-pbr
-BuildRequires: python-setuptools
+BuildRequires: python-wrapt
Requires: python-Babel >= 1.3
+Requires: python-funcsigs >= 0.4
Requires: python-six >= 1.9.0
Requires: python-wrapt >= 1.7.0
BuildRoot: %{_tmppath}/%{name}-%{version}-build
@@ -50,9 +52,6 @@
%install
python setup.py install --prefix=%{_prefix} --root=%{buildroot}
-#%check
-#nosetests
-
%files
%defattr(-,root,root,-)
%doc README.rst ChangeLog LICENSE AUTHORS
++++++ debtcollector-0.8.0.tar.gz -> debtcollector-1.3.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/.coveragerc
new/debtcollector-1.3.0/.coveragerc
--- old/debtcollector-0.8.0/.coveragerc 2015-09-08 17:29:41.000000000 +0200
+++ new/debtcollector-1.3.0/.coveragerc 2016-02-10 00:15:07.000000000 +0100
@@ -4,4 +4,4 @@
omit = debtcollector/tests/*,debtcollector/openstack/*
[report]
-ignore-errors = True
\ No newline at end of file
+ignore_errors = True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/AUTHORS
new/debtcollector-1.3.0/AUTHORS
--- old/debtcollector-0.8.0/AUTHORS 2015-09-08 17:30:03.000000000 +0200
+++ new/debtcollector-1.3.0/AUTHORS 2016-02-10 00:15:30.000000000 +0100
@@ -1,6 +1,14 @@
+ChangBo Guo(gcb) <[email protected]>
+Davanum Srinivas <[email protected]>
Doug Hellmann <[email protected]>
+Graham Hayes <[email protected]>
+Jamie Lennox <[email protected]>
Jamie Lennox <[email protected]>
Joe Gordon <[email protected]>
Joshua Harlow <[email protected]>
Joshua Harlow <[email protected]>
Matthew Treinish <[email protected]>
+Monty Taylor <[email protected]>
+THOMAS J. COCOZZELLO <[email protected]>
+caoyue <[email protected]>
+janonymous <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/ChangeLog
new/debtcollector-1.3.0/ChangeLog
--- old/debtcollector-0.8.0/ChangeLog 2015-09-08 17:30:03.000000000 +0200
+++ new/debtcollector-1.3.0/ChangeLog 2016-02-10 00:15:30.000000000 +0100
@@ -1,6 +1,53 @@
CHANGES
=======
+1.3.0
+-----
+
+* Updated from global requirements
+* Add debug testenv in tox
+
+1.2.0
+-----
+
+* Add updated_kwarg_default_value decorator
+* Allow replacing a keyword argument
+* Add 'removed_class' class decorator
+* py26/py33 are no longer supported by Infra's CI
+
+1.1.0
+-----
+
+* Add removals.remove note about metaclasses
+
+1.0.0
+-----
+
+* Updated from global requirements
+* Update get_class_name from olso.utils
+* Remove Python 2.6 classifier
+* Remove python 2.6 and cleanup tox.ini
+* Add 'moved_read_only_property' descriptor
+
+0.10.0
+------
+
+* Add ability to disable warnings being emitted
+
+0.9.0
+-----
+
+* Add a 'removed_property' descriptor class
+* No need for Oslo Incubator Sync
+* docs - Set pbr 'warnerrors' option for doc build
+* Include changelog/history in docs
+* tweak language in readme
+* Enhance the README
+* Change ignore-errors to ignore_errors
+* Updated from global requirements
+* Activate pep8 check that _ is imported
+* Add a moved function helper
+
0.8.0
-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/PKG-INFO
new/debtcollector-1.3.0/PKG-INFO
--- old/debtcollector-0.8.0/PKG-INFO 2015-09-08 17:30:03.000000000 +0200
+++ new/debtcollector-1.3.0/PKG-INFO 2016-02-10 00:15:30.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: debtcollector
-Version: 0.8.0
+Version: 1.3.0
Summary: A collection of Python deprecation patterns and strategies that help
you collect your technical debt in a non-destructive manner.
Home-page: http://www.openstack.org/
Author: OpenStack
@@ -18,7 +18,14 @@
:alt: Downloads
A collection of Python deprecation patterns and strategies that help
you
- collect your technical debt in a non-destructive manner.
+ collect your technical debt in a non-destructive manner. The goal of
this
+ library is to provide well documented developer facing deprecation
+ patterns that start of with a basic set and can expand into a larger
+ set of patterns as time goes on. The desired output of these patterns
+ is to apply the warnings module to emit DeprecationWarning or
PendingDeprecationWarning
+ or similar derivative to developers using libraries (or potentially
+ applications) about future deprecations.
+
* Free software: Apache license
* Documentation: http://docs.openstack.org/developer/debtcollector
@@ -35,7 +42,6 @@
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/README.rst
new/debtcollector-1.3.0/README.rst
--- old/debtcollector-0.8.0/README.rst 2015-09-08 17:29:41.000000000 +0200
+++ new/debtcollector-1.3.0/README.rst 2016-02-10 00:15:07.000000000 +0100
@@ -10,9 +10,16 @@
:alt: Downloads
A collection of Python deprecation patterns and strategies that help you
-collect your technical debt in a non-destructive manner.
+collect your technical debt in a non-destructive manner. The goal of this
+library is to provide well documented developer facing deprecation
+patterns that start of with a basic set and can expand into a larger
+set of patterns as time goes on. The desired output of these patterns
+is to apply the warnings module to emit DeprecationWarning or
PendingDeprecationWarning
+or similar derivative to developers using libraries (or potentially
+applications) about future deprecations.
+
* Free software: Apache license
* Documentation: http://docs.openstack.org/developer/debtcollector
* Source: http://git.openstack.org/cgit/openstack/debtcollector
-* Bugs: http://bugs.launchpad.net/debtcollector
\ No newline at end of file
+* Bugs: http://bugs.launchpad.net/debtcollector
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/debtcollector/_utils.py
new/debtcollector-1.3.0/debtcollector/_utils.py
--- old/debtcollector-0.8.0/debtcollector/_utils.py 2015-09-08
17:29:41.000000000 +0200
+++ new/debtcollector-1.3.0/debtcollector/_utils.py 2016-02-10
00:15:07.000000000 +0100
@@ -14,6 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import functools
import inspect
import types
import warnings
@@ -30,6 +31,7 @@
# and see https://docs.python.org/2/reference/executionmodel.html (and likely
# others)...
_BUILTIN_MODULES = ('builtins', '__builtin__', '__builtins__', 'exceptions')
+_enabled = True
def deprecation(message, stacklevel=None, category=None):
@@ -49,6 +51,8 @@
avoid doing by always giving at *least* N + 1 release for users to address
the deprecation warnings).
"""
+ if not _enabled:
+ return
if category is None:
category = DeprecationWarning
if stacklevel is None:
@@ -85,6 +89,18 @@
return ''.join(message_components)
+def get_assigned(decorator):
+ """Helper to fix/workaround https://bugs.python.org/issue3445"""
+ if six.PY3:
+ return functools.WRAPPER_ASSIGNMENTS
+ else:
+ assigned = []
+ for attr_name in functools.WRAPPER_ASSIGNMENTS:
+ if hasattr(decorator, attr_name):
+ assigned.append(attr_name)
+ return tuple(assigned)
+
+
def get_class_name(obj, fully_qualified=True):
"""Get class name for object.
@@ -100,21 +116,12 @@
pass
else:
if built_in:
- try:
- return obj.__qualname__
- except AttributeError:
- return obj.__name__
- pieces = []
- try:
- pieces.append(obj.__qualname__)
- except AttributeError:
- pieces.append(obj.__name__)
- if fully_qualified:
- try:
- pieces.insert(0, obj.__module__)
- except AttributeError:
- pass
- return '.'.join(pieces)
+ return obj.__name__
+
+ if fully_qualified and hasattr(obj, '__module__'):
+ return '%s.%s' % (obj.__module__, obj.__name__)
+ else:
+ return obj.__name__
def get_method_self(method):
@@ -164,4 +171,10 @@
parts = (im_class.__module__, im_class.__qualname__)
except AttributeError:
parts = (im_class.__module__, im_class.__name__)
- return '.'.join(parts)
+ # When running under sphinx it appears this can be none? if so just
+ # don't include it...
+ mod, rest = (parts[0], parts[1:])
+ if not mod:
+ return '.'.join(rest)
+ else:
+ return '.'.join(parts)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/debtcollector-0.8.0/debtcollector/fixtures/disable.py
new/debtcollector-1.3.0/debtcollector/fixtures/disable.py
--- old/debtcollector-0.8.0/debtcollector/fixtures/disable.py 1970-01-01
01:00:00.000000000 +0100
+++ new/debtcollector-1.3.0/debtcollector/fixtures/disable.py 2016-02-10
00:15:07.000000000 +0100
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2015 Yahoo! Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from __future__ import absolute_import
+
+import fixtures
+
+from debtcollector import _utils
+
+
+class DisableFixture(fixtures.Fixture):
+ """Fixture that disables debtcollector triggered warnings.
+
+ This does **not** disable warnings calls emitted by other libraries.
+
+ This can be used like::
+
+ from debtcollector.fixtures import disable
+
+ with disable.DisableFixture():
+ <some code that calls into depreciated code>
+ """
+
+ def _setUp(self):
+ self.addCleanup(setattr, _utils, "_enabled", True)
+ _utils._enabled = False
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/debtcollector/moves.py
new/debtcollector-1.3.0/debtcollector/moves.py
--- old/debtcollector-0.8.0/debtcollector/moves.py 2015-09-08
17:29:41.000000000 +0200
+++ new/debtcollector-1.3.0/debtcollector/moves.py 2016-02-10
00:15:07.000000000 +0100
@@ -22,7 +22,8 @@
_KIND_MOVED_PREFIX_TPL = "%s '%s' has moved to '%s'"
_CLASS_MOVED_PREFIX_TPL = "Class '%s' has moved to '%s'"
-_MOVED_METHOD_POSTFIX = "()"
+_MOVED_CALLABLE_POSTFIX = "()"
+_FUNC_MOVED_PREFIX_TPL = "Function '%s' has moved to '%s'"
def _moved_decorator(kind, new_attribute_name, message=None,
@@ -35,7 +36,7 @@
if attr_postfix:
old_attribute_name += attr_postfix
- @six.wraps(f)
+ @six.wraps(f, assigned=_utils.get_assigned(f))
def wrapper(self, *args, **kwargs):
base_name = _utils.get_class_name(self, fully_qualified=False)
if fully_qualified:
@@ -56,23 +57,101 @@
return decorator
+def moved_function(new_func, old_func_name, old_module_name,
+ message=None, version=None, removal_version=None,
+ stacklevel=3, category=None):
+ """Deprecates a function that was moved to another location.
+
+ This generates a wrapper around ``new_func`` that will emit a deprecation
+ warning when called. The warning message will include the new location
+ to obtain the function from.
+ """
+ new_func_full_name = _utils.get_callable_name(new_func)
+ new_func_full_name += _MOVED_CALLABLE_POSTFIX
+ old_func_full_name = ".".join([old_module_name, old_func_name])
+ old_func_full_name += _MOVED_CALLABLE_POSTFIX
+ prefix = _FUNC_MOVED_PREFIX_TPL % (old_func_full_name, new_func_full_name)
+ out_message = _utils.generate_message(prefix,
+ message=message, version=version,
+ removal_version=removal_version)
+
+ @six.wraps(new_func, assigned=_utils.get_assigned(new_func))
+ def old_new_func(*args, **kwargs):
+ _utils.deprecation(out_message, stacklevel=stacklevel,
+ category=category)
+ return new_func(*args, **kwargs)
+
+ old_new_func.__name__ = old_func_name
+ old_new_func.__module__ = old_module_name
+ return old_new_func
+
+
+class moved_read_only_property(object):
+ """Descriptor for read-only properties moved to another location.
+
+ This works like the ``@property`` descriptor but can be used instead to
+ provide the same functionality and also interact with the :mod:`warnings`
+ module to warn when a property is accessed, so that users of those
+ properties can know that a previously read-only property at a prior
+ location/name has moved to another location/name.
+
+ :param old_name: old attribute location/name
+ :param new_name: new attribute location/name
+ :param version: version string (represents the version this deprecation
+ was created in)
+ :param removal_version: version string (represents the version this
+ deprecation will be removed in); a string
+ of '?' will denote this will be removed in
+ some future unknown version
+ :param stacklevel: stacklevel used in the :func:`warnings.warn` function
+ to locate where the users code is when reporting the
+ deprecation call (the default being 3)
+ :param category: the :mod:`warnings` category to use, defaults to
+ :py:class:`DeprecationWarning` if not provided
+ """
+
+ def __init__(self, old_name, new_name,
+ version=None, removal_version=None,
+ stacklevel=3, category=None):
+ self._old_name = old_name
+ self._new_name = new_name
+ self._message = _utils.generate_message(
+ "Read-only property '%s' has moved"
+ " to '%s'" % (self._old_name, self._new_name),
+ version=version, removal_version=removal_version)
+ self._stacklevel = stacklevel
+ self._category = category
+
+ def __get__(self, instance, owner):
+ _utils.deprecation(self._message,
+ stacklevel=self._stacklevel,
+ category=self._category)
+ # This handles the descriptor being applied on a
+ # instance or a class and makes both work correctly...
+ if instance is not None:
+ real_owner = instance
+ else:
+ real_owner = owner
+ return getattr(real_owner, self._new_name)
+
+
def moved_method(new_method_name, message=None,
version=None, removal_version=None, stacklevel=3,
category=None):
- """Decorates a *instance* method that was moved to another location."""
- if not new_method_name.endswith(_MOVED_METHOD_POSTFIX):
- new_method_name += _MOVED_METHOD_POSTFIX
+ """Decorates an *instance* method that was moved to another location."""
+ if not new_method_name.endswith(_MOVED_CALLABLE_POSTFIX):
+ new_method_name += _MOVED_CALLABLE_POSTFIX
return _moved_decorator('Method', new_method_name, message=message,
version=version, removal_version=removal_version,
stacklevel=stacklevel,
- attr_postfix=_MOVED_METHOD_POSTFIX,
+ attr_postfix=_MOVED_CALLABLE_POSTFIX,
category=category)
def moved_property(new_attribute_name, message=None,
version=None, removal_version=None, stacklevel=3,
category=None):
- """Decorates a *instance* property that was moved to another location."""
+ """Decorates an *instance* property that was moved to another location."""
return _moved_decorator('Property', new_attribute_name, message=message,
version=version, removal_version=removal_version,
stacklevel=stacklevel, category=category)
@@ -103,7 +182,7 @@
def decorator(f):
- @six.wraps(f, assigned=("__name__", "__doc__"))
+ @six.wraps(f, assigned=_utils.get_assigned(f))
def wrapper(self, *args, **kwargs):
_utils.deprecation(out_message, stacklevel=stacklevel,
category=category)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/debtcollector/removals.py
new/debtcollector-1.3.0/debtcollector/removals.py
--- old/debtcollector-0.8.0/debtcollector/removals.py 2015-09-08
17:29:41.000000000 +0200
+++ new/debtcollector-1.3.0/debtcollector/removals.py 2016-02-10
00:15:07.000000000 +0100
@@ -21,14 +21,155 @@
from debtcollector import _utils
-def _get_module_name(mod):
- return _utils.get_qualified_name(mod)[1]
+def _get_qualified_name(obj):
+ return _utils.get_qualified_name(obj)[1]
+
+
+def _fetch_first_result(fget, fset, fdel, apply_func, value_not_found=None):
+ """Fetch first non-none/empty result of applying ``apply_func``."""
+ for f in filter(None, (fget, fset, fdel)):
+ result = apply_func(f)
+ if result:
+ return result
+ return value_not_found
+
+
+class removed_property(object):
+ """Property descriptor that deprecates a property.
+
+ This works like the ``@property`` descriptor but can be used instead to
+ provide the same functionality and also interact with the :mod:`warnings`
+ module to warn when a property is accessed, set and/or deleted.
+
+ :param message: string used as ending contents of the deprecate message
+ :param version: version string (represents the version this deprecation
+ was created in)
+ :param removal_version: version string (represents the version this
+ deprecation will be removed in); a string
+ of '?' will denote this will be removed in
+ some future unknown version
+ :param stacklevel: stacklevel used in the :func:`warnings.warn` function
+ to locate where the users code is when reporting the
+ deprecation call (the default being 3)
+ :param category: the :mod:`warnings` category to use, defaults to
+ :py:class:`DeprecationWarning` if not provided
+ """
+
+ # Message templates that will be turned into real messages as needed.
+ _PROPERTY_GONE_TPLS = {
+ 'set': "Setting the '%s' property is deprecated",
+ 'get': "Reading the '%s' property is deprecated",
+ 'delete': "Deleting the '%s' property is deprecated",
+ }
+
+ def __init__(self, fget=None, fset=None, fdel=None, doc=None,
+ stacklevel=3, category=DeprecationWarning,
+ version=None, removal_version=None, message=None):
+ self.fset = fset
+ self.fget = fget
+ self.fdel = fdel
+ self.stacklevel = stacklevel
+ self.category = category
+ self.version = version
+ self.removal_version = removal_version
+ self.message = message
+ if doc is None and inspect.isfunction(fget):
+ doc = getattr(fget, '__doc__', None)
+ self._message_cache = {}
+ self.__doc__ = doc
+
+ def _fetch_message_from_cache(self, kind):
+ try:
+ out_message = self._message_cache[kind]
+ except KeyError:
+ prefix_tpl = self._PROPERTY_GONE_TPLS[kind]
+ prefix = prefix_tpl % _fetch_first_result(
+ self.fget, self.fset, self.fdel, _get_qualified_name,
+ value_not_found="???")
+ out_message = _utils.generate_message(
+ prefix, message=self.message, version=self.version,
+ removal_version=self.removal_version)
+ self._message_cache[kind] = out_message
+ return out_message
+
+ def __call__(self, fget, **kwargs):
+ self.fget = fget
+ self.message = kwargs.get('message', self.message)
+ self.version = kwargs.get('version', self.version)
+ self.removal_version = kwargs.get('removal_version',
+ self.removal_version)
+ self.stacklevel = kwargs.get('stacklevel', self.stacklevel)
+ self.category = kwargs.get('category', self.category)
+ self.__doc__ = kwargs.get('doc',
+ getattr(fget, '__doc__', self.__doc__))
+ # Regenerate all the messages...
+ self._message_cache.clear()
+ return self
+
+ def __delete__(self, obj):
+ if self.fdel is None:
+ raise AttributeError("can't delete attribute")
+ out_message = self._fetch_message_from_cache('delete')
+ _utils.deprecation(out_message, stacklevel=self.stacklevel,
+ category=self.category)
+ self.fdel(obj)
+
+ def __set__(self, obj, value):
+ if self.fset is None:
+ raise AttributeError("can't set attribute")
+ out_message = self._fetch_message_from_cache('set')
+ _utils.deprecation(out_message, stacklevel=self.stacklevel,
+ category=self.category)
+ self.fset(obj, value)
+
+ def __get__(self, obj, value):
+ if obj is None:
+ return self
+ if self.fget is None:
+ raise AttributeError("unreadable attribute")
+ out_message = self._fetch_message_from_cache('get')
+ _utils.deprecation(out_message, stacklevel=self.stacklevel,
+ category=self.category)
+ return self.fget(obj)
+
+ def getter(self, fget):
+ o = type(self)(fget, self.fset, self.fdel, self.__doc__)
+ o.message = self.message
+ o.version = self.version
+ o.stacklevel = self.stacklevel
+ o.removal_version = self.removal_version
+ o.category = self.category
+ return o
+
+ def setter(self, fset):
+ o = type(self)(self.fget, fset, self.fdel, self.__doc__)
+ o.message = self.message
+ o.version = self.version
+ o.stacklevel = self.stacklevel
+ o.removal_version = self.removal_version
+ o.category = self.category
+ return o
+
+ def deleter(self, fdel):
+ o = type(self)(self.fget, self.fset, fdel, self.__doc__)
+ o.message = self.message
+ o.version = self.version
+ o.stacklevel = self.stacklevel
+ o.removal_version = self.removal_version
+ o.category = self.category
+ return o
def remove(f=None, message=None, version=None, removal_version=None,
stacklevel=3, category=None):
"""Decorates a function, method, or class to emit a deprecation warning
+ Due to limitations of the wrapt library (and python) itself, if this
+ is applied to subclasses of metaclasses then it likely will not work
+ as expected. More information can be found at bug #1520397 to see if
+ this situation affects your usage of this *universal* decorator, for
+ this specific scenario please use :py:func:`.removed_class` instead.
+
:param str message: A message to include in the deprecation warning
:param str version: Specify what version the removed function is present in
:param str removal_version: What version the function will be removed. If
@@ -64,7 +205,7 @@
if inspect.isclass(f):
prefix_pre = "Using class"
thing_post = ''
- module_name = _get_module_name(inspect.getmodule(f))
+ module_name = _get_qualified_name(inspect.getmodule(f))
if module_name == '__main__':
f_name = _utils.get_class_name(
f, fully_qualified=False)
@@ -74,7 +215,7 @@
# Decorator was a used on a function
else:
thing_post = '()'
- module_name = _get_module_name(inspect.getmodule(f))
+ module_name = _get_qualified_name(inspect.getmodule(f))
if module_name != '__main__':
f_name = _utils.get_callable_name(f)
# Decorator was used on a classmethod or instancemethod
@@ -122,6 +263,39 @@
return wrapper
+def removed_class(cls_name, replacement=None, message=None,
+ version=None, removal_version=None, stacklevel=3,
+ category=None):
+ """Decorates a class to denote that it will be removed at some point."""
+
+ def _wrap_it(old_init, out_message):
+
+ @six.wraps(old_init, assigned=_utils.get_assigned(old_init))
+ def new_init(self, *args, **kwargs):
+ _utils.deprecation(out_message, stacklevel=stacklevel,
+ category=category)
+ return old_init(self, *args, **kwargs)
+
+ return new_init
+
+ def _check_it(cls):
+ if not inspect.isclass(cls):
+ _qual, type_name = _utils.get_qualified_name(type(cls))
+ raise TypeError("Unexpected class type '%s' (expected"
+ " class type only)" % type_name)
+
+ def _cls_decorator(cls):
+ _check_it(cls)
+ out_message = _utils.generate_message(
+ "Using class '%s' (either directly or via inheritance)"
+ " is deprecated" % cls_name, postfix=None, message=message,
+ version=version, removal_version=removal_version)
+ cls.__init__ = _wrap_it(cls.__init__, out_message)
+ return cls
+
+ return _cls_decorator
+
+
def removed_module(module, replacement=None, message=None,
version=None, removal_version=None, stacklevel=3,
category=None):
@@ -140,7 +314,7 @@
``DeprecationWarning`` when none is provided)
"""
if inspect.ismodule(module):
- module_name = _get_module_name(module)
+ module_name = _get_qualified_name(module)
elif isinstance(module, six.string_types):
module_name = module
else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/debtcollector/renames.py
new/debtcollector-1.3.0/debtcollector/renames.py
--- old/debtcollector-0.8.0/debtcollector/renames.py 2015-09-08
17:29:41.000000000 +0200
+++ new/debtcollector-1.3.0/debtcollector/renames.py 2016-02-10
00:15:07.000000000 +0100
@@ -24,7 +24,7 @@
def renamed_kwarg(old_name, new_name, message=None,
version=None, removal_version=None, stacklevel=3,
- category=None):
+ category=None, replace=False):
"""Decorates a kwarg accepting function to deprecate a renamed kwarg."""
prefix = _KWARG_RENAMED_PREFIX_TPL % old_name
@@ -35,11 +35,13 @@
def decorator(f):
- @six.wraps(f)
+ @six.wraps(f, assigned=_utils.get_assigned(f))
def wrapper(*args, **kwargs):
if old_name in kwargs:
_utils.deprecation(out_message,
stacklevel=stacklevel, category=category)
+ if replace:
+ kwargs.setdefault(new_name, kwargs.pop(old_name))
return f(*args, **kwargs)
return wrapper
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/debtcollector-0.8.0/debtcollector/tests/test_deprecation.py
new/debtcollector-1.3.0/debtcollector/tests/test_deprecation.py
--- old/debtcollector-0.8.0/debtcollector/tests/test_deprecation.py
2015-09-08 17:29:41.000000000 +0200
+++ new/debtcollector-1.3.0/debtcollector/tests/test_deprecation.py
2016-02-10 00:15:07.000000000 +0100
@@ -15,10 +15,12 @@
import warnings
import debtcollector
+from debtcollector.fixtures import disable
from debtcollector import moves
from debtcollector import removals
from debtcollector import renames
from debtcollector.tests import base as test_base
+from debtcollector import updating
@renames.renamed_kwarg('blip', 'blop')
@@ -31,6 +33,16 @@
return (blip, blop)
[email protected]_kwarg('blip', 'blop', replace=True)
+def blip_blop_3(blop=1):
+ return blop
+
+
[email protected]_kwarg_default_value('type', 'cat', 'feline')
+def blip_blop_blip(type='cat'):
+ return "The %s meowed quietly" % type
+
+
class WoofWoof(object):
@property
def bark(self):
@@ -66,6 +78,17 @@
return 'supermeow'
+class Giraffe(object):
+ color = 'orange'
+ colour = moves.moved_read_only_property('colour', 'color')
+
+ @property
+ def height(self):
+ return 2
+
+ heightt = moves.moved_read_only_property('heightt', 'height')
+
+
class NewHotness(object):
def hot(self):
return 'cold'
@@ -91,6 +114,14 @@
return True
+def yellow_sun():
+ """Yellow."""
+ return True
+
+
+yellowish_sun = moves.moved_function(yellow_sun, 'yellowish_sun', __name__)
+
+
@removals.remove()
class EFSF(object):
pass
@@ -101,11 +132,39 @@
pass
[email protected]_class("StarLord")
+class StarLord(object):
+ def __init__(self):
+ self.name = "star"
+
+
+class StarLordJr(StarLord):
+ def __init__(self, name):
+ super(StarLordJr, self).__init__()
+ self.name = name
+
+
class ThingB(object):
@removals.remove()
def black_tristars(self):
pass
+ @removals.removed_property
+ def green_tristars(self):
+ return 'green'
+
+ @green_tristars.setter
+ def green_tristars(self, value):
+ pass
+
+ @green_tristars.deleter
+ def green_tristars(self):
+ pass
+
+ @removals.removed_property(message="stop using me")
+ def green_blue_tristars(self):
+ return 'green-blue'
+
@removals.remove(category=PendingDeprecationWarning)
def blue_tristars(self):
pass
@@ -191,6 +250,14 @@
self.assertEqual('woof', dog.burk)
self.assertEqual('woof', dog.bark)
+ def test_readonly_move(self):
+ with warnings.catch_warnings(record=True) as capture:
+ warnings.simplefilter("always")
+ self.assertEqual('orange', Giraffe.colour)
+ g = Giraffe()
+ self.assertEqual(2, g.heightt)
+ self.assertEqual(2, len(capture))
+
def test_warnings_emitted(self):
dog = WoofWoof()
with warnings.catch_warnings(record=True) as capture:
@@ -217,6 +284,34 @@
self.assertEqual(0, len(capture))
+class DisabledTest(test_base.TestCase):
+ def test_basics(self):
+ dog = WoofWoof()
+ c = KittyKat()
+ with warnings.catch_warnings(record=True) as capture:
+ warnings.simplefilter("always")
+ with disable.DisableFixture():
+ self.assertTrue(yellowish_sun())
+ self.assertEqual('woof', dog.berk)
+ self.assertEqual('supermeow', c.meow())
+ self.assertEqual(0, len(capture))
+
+
+class MovedFunctionTest(test_base.TestCase):
+ def test_basics(self):
+ self.assertTrue(yellowish_sun())
+ self.assertTrue(yellow_sun())
+ self.assertEqual("Yellow.", yellowish_sun.__doc__)
+
+ def test_warnings_emitted(self):
+ with warnings.catch_warnings(record=True) as capture:
+ warnings.simplefilter("always")
+ self.assertTrue(yellowish_sun())
+ self.assertEqual(1, len(capture))
+ w = capture[0]
+ self.assertEqual(DeprecationWarning, w.category)
+
+
class MovedMethodTest(test_base.TestCase):
def test_basics(self):
c = KittyKat()
@@ -255,6 +350,8 @@
self.assertEqual((2, 1), blip_blop(blip=2))
self.assertEqual((1, 2), blip_blop(blop=2))
self.assertEqual((2, 2), blip_blop(blip=2, blop=2))
+ self.assertEqual(2, blip_blop_3(blip=2))
+ self.assertEqual(2, blip_blop_3(blop=2))
def test_warnings_emitted(self):
with warnings.catch_warnings(record=True) as capture:
@@ -263,6 +360,12 @@
self.assertEqual(1, len(capture))
w = capture[0]
self.assertEqual(DeprecationWarning, w.category)
+ with warnings.catch_warnings(record=True) as capture:
+ warnings.simplefilter("always")
+ self.assertEqual(2, blip_blop_3(blip=2))
+ self.assertEqual(1, len(capture))
+ w = capture[0]
+ self.assertEqual(DeprecationWarning, w.category)
def test_warnings_emitted_classmethod(self):
with warnings.catch_warnings(record=True) as capture:
@@ -289,6 +392,28 @@
warnings.simplefilter("always")
self.assertEqual((1, 2), blip_blop(blop=2))
self.assertEqual(0, len(capture))
+ with warnings.catch_warnings(record=True) as capture:
+ warnings.simplefilter("always")
+ self.assertEqual(2, blip_blop_3(blop=2))
+ self.assertEqual(0, len(capture))
+
+
+class UpdatedArgsTest(test_base.TestCase):
+ def test_basic(self):
+ with warnings.catch_warnings(record=True) as capture:
+ warnings.simplefilter("always")
+ self.assertEqual('The cat meowed quietly', blip_blop_blip())
+ self.assertEqual(1, len(capture))
+ w = capture[0]
+ self.assertEqual(FutureWarning, w.category)
+
+ def test_kwarg_set(self):
+ with warnings.catch_warnings(record=True) as capture:
+ warnings.simplefilter("always")
+ self.assertEqual(
+ 'The kitten meowed quietly',
+ blip_blop_blip(type='kitten'))
+ self.assertEqual(0, len(capture))
class RemovalTests(test_base.TestCase):
@@ -334,6 +459,27 @@
self.assertEqual(2, f())
self.assertEqual(0, len(capture))
+ def test_warnings_emitted_property(self):
+ with warnings.catch_warnings(record=True) as capture:
+ warnings.simplefilter("always")
+ o = ThingB()
+ self.assertEqual('green', o.green_tristars)
+ o.green_tristars = 'b'
+ del o.green_tristars
+ self.assertEqual(3, len(capture))
+ w = capture[0]
+ self.assertEqual(DeprecationWarning, w.category)
+
+ def test_warnings_emitted_property_custom_message(self):
+ with warnings.catch_warnings(record=True) as capture:
+ warnings.simplefilter("always")
+ o = ThingB()
+ self.assertEqual('green-blue', o.green_blue_tristars)
+ self.assertEqual(1, len(capture))
+ w = capture[0]
+ self.assertIn('stop using me', str(w.message))
+ self.assertEqual(DeprecationWarning, w.category)
+
def test_warnings_emitted_function_args(self):
with warnings.catch_warnings(record=True) as capture:
warnings.simplefilter("always")
@@ -382,6 +528,24 @@
w = capture[0]
self.assertEqual(PendingDeprecationWarning, w.category)
+ def test_pending_warnings_emitted_class_direct(self):
+ with warnings.catch_warnings(record=True) as capture:
+ warnings.simplefilter("always")
+ s = StarLord()
+ self.assertEqual(1, len(capture))
+ w = capture[0]
+ self.assertEqual(DeprecationWarning, w.category)
+ self.assertEqual("star", s.name)
+
+ def test_pending_warnings_emitted_class_inherit(self):
+ with warnings.catch_warnings(record=True) as capture:
+ warnings.simplefilter("always")
+ s = StarLordJr("star_jr")
+ self.assertEqual(1, len(capture))
+ w = capture[0]
+ self.assertEqual(DeprecationWarning, w.category)
+ self.assertEqual("star_jr", s.name)
+
def test_warnings_emitted_instancemethod(self):
zeon = ThingB()
with warnings.catch_warnings(record=True) as capture:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/debtcollector/updating.py
new/debtcollector-1.3.0/debtcollector/updating.py
--- old/debtcollector-0.8.0/debtcollector/updating.py 1970-01-01
01:00:00.000000000 +0100
+++ new/debtcollector-1.3.0/debtcollector/updating.py 2016-02-10
00:15:07.000000000 +0100
@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2015 Yahoo! Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import six
+if six.PY3:
+ import inspect
+ Parameter = inspect.Parameter
+ Signature = inspect.Signature
+ get_signature = inspect.signature
+else:
+ # Provide an equivalent but use funcsigs instead...
+ import funcsigs
+ Parameter = funcsigs.Parameter
+ Signature = funcsigs.Signature
+ get_signature = funcsigs.signature
+
+from debtcollector import _utils
+
+_KWARG_UPDATED_POSTFIX_TPL = (', please update the code to explicitly set %s '
+ 'as the value')
+_KWARG_UPDATED_PREFIX_TPL = ('The %s argument is changing its default value '
+ 'to %s')
+
+
+def updated_kwarg_default_value(name, old_value, new_value, message=None,
+ version=None, stacklevel=3,
+ category=FutureWarning):
+
+ """Decorates a kwarg accepting function to change the default value"""
+
+ prefix = _KWARG_UPDATED_PREFIX_TPL % (name, new_value)
+ postfix = _KWARG_UPDATED_POSTFIX_TPL % old_value
+ out_message = _utils.generate_message(
+ prefix, postfix=postfix, message=message, version=version)
+
+ def decorator(f):
+ sig = get_signature(f)
+ varnames = list(six.iterkeys(sig.parameters))
+
+ @six.wraps(f)
+ def wrapper(*args, **kwargs):
+ explicit_params = set(
+ varnames[:len(args)] + list(kwargs.keys())
+ )
+ allparams = set(varnames)
+ default_params = set(allparams - explicit_params)
+ if name in default_params:
+ _utils.deprecation(out_message,
+ stacklevel=stacklevel, category=category)
+ return f(*args, **kwargs)
+
+ return wrapper
+
+ return decorator
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/debtcollector.egg-info/PKG-INFO
new/debtcollector-1.3.0/debtcollector.egg-info/PKG-INFO
--- old/debtcollector-0.8.0/debtcollector.egg-info/PKG-INFO 2015-09-08
17:30:03.000000000 +0200
+++ new/debtcollector-1.3.0/debtcollector.egg-info/PKG-INFO 2016-02-10
00:15:30.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: debtcollector
-Version: 0.8.0
+Version: 1.3.0
Summary: A collection of Python deprecation patterns and strategies that help
you collect your technical debt in a non-destructive manner.
Home-page: http://www.openstack.org/
Author: OpenStack
@@ -18,7 +18,14 @@
:alt: Downloads
A collection of Python deprecation patterns and strategies that help
you
- collect your technical debt in a non-destructive manner.
+ collect your technical debt in a non-destructive manner. The goal of
this
+ library is to provide well documented developer facing deprecation
+ patterns that start of with a basic set and can expand into a larger
+ set of patterns as time goes on. The desired output of these patterns
+ is to apply the warnings module to emit DeprecationWarning or
PendingDeprecationWarning
+ or similar derivative to developers using libraries (or potentially
+ applications) about future deprecations.
+
* Free software: Apache license
* Documentation: http://docs.openstack.org/developer/debtcollector
@@ -35,7 +42,6 @@
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/debtcollector-0.8.0/debtcollector.egg-info/SOURCES.txt
new/debtcollector-1.3.0/debtcollector.egg-info/SOURCES.txt
--- old/debtcollector-0.8.0/debtcollector.egg-info/SOURCES.txt 2015-09-08
17:30:03.000000000 +0200
+++ new/debtcollector-1.3.0/debtcollector.egg-info/SOURCES.txt 2016-02-10
00:15:30.000000000 +0100
@@ -9,7 +9,6 @@
MANIFEST.in
README.rst
babel.cfg
-openstack-common.conf
requirements.txt
setup.cfg
setup.py
@@ -20,6 +19,7 @@
debtcollector/moves.py
debtcollector/removals.py
debtcollector/renames.py
+debtcollector/updating.py
debtcollector.egg-info/PKG-INFO
debtcollector.egg-info/SOURCES.txt
debtcollector.egg-info/dependency_links.txt
@@ -27,6 +27,8 @@
debtcollector.egg-info/pbr.json
debtcollector.egg-info/requires.txt
debtcollector.egg-info/top_level.txt
+debtcollector/fixtures/__init__.py
+debtcollector/fixtures/disable.py
debtcollector/tests/__init__.py
debtcollector/tests/base.py
debtcollector/tests/test_deprecation.py
@@ -34,5 +36,6 @@
doc/source/conf.py
doc/source/contributing.rst
doc/source/examples.rst
+doc/source/history.rst
doc/source/index.rst
doc/source/installation.rst
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/debtcollector.egg-info/pbr.json
new/debtcollector-1.3.0/debtcollector.egg-info/pbr.json
--- old/debtcollector-0.8.0/debtcollector.egg-info/pbr.json 2015-09-08
17:30:03.000000000 +0200
+++ new/debtcollector-1.3.0/debtcollector.egg-info/pbr.json 2016-02-10
00:15:30.000000000 +0100
@@ -1 +1 @@
-{"is_release": true, "git_version": "ceb020b"}
\ No newline at end of file
+{"git_version": "e40dfd5", "is_release": true}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/debtcollector-0.8.0/debtcollector.egg-info/requires.txt
new/debtcollector-1.3.0/debtcollector.egg-info/requires.txt
--- old/debtcollector-0.8.0/debtcollector.egg-info/requires.txt 2015-09-08
17:30:03.000000000 +0200
+++ new/debtcollector-1.3.0/debtcollector.egg-info/requires.txt 2016-02-10
00:15:30.000000000 +0100
@@ -1,4 +1,7 @@
-pbr<2.0,>=1.6
+pbr>=1.6
Babel>=1.3
six>=1.9.0
wrapt>=1.7.0
+
+[:(python_version=='2.7' or python_version=='2.6')]
+funcsigs>=0.4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/doc/source/api.rst
new/debtcollector-1.3.0/doc/source/api.rst
--- old/debtcollector-0.8.0/doc/source/api.rst 2015-09-08 17:29:41.000000000
+0200
+++ new/debtcollector-1.3.0/doc/source/api.rst 2016-02-10 00:15:07.000000000
+0100
@@ -31,3 +31,8 @@
--------
.. automodule:: debtcollector.removals
+
+Fixtures
+--------
+
+.. automodule:: debtcollector.fixtures.disable
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/doc/source/examples.rst
new/debtcollector-1.3.0/doc/source/examples.rst
--- old/debtcollector-0.8.0/doc/source/examples.rst 2015-09-08
17:29:41.000000000 +0200
+++ new/debtcollector-1.3.0/doc/source/examples.rst 2016-02-10
00:15:07.000000000 +0100
@@ -38,7 +38,7 @@
>>> from debtcollector import removals
>>> import warnings
>>> warnings.simplefilter('always')
- >>> @removals.remove
+ >>> @removals.removed_class("Pinto")
... class Pinto(object):
... pass
...
@@ -48,7 +48,7 @@
.. testoutput::
- __main__:1: DeprecationWarning: Using class 'Pinto' is deprecated
+ __main__:1: DeprecationWarning: Using class 'Pinto' (either directly or
via inheritance) is deprecated
A basic example to do just this (on a classmethod):
@@ -71,6 +71,42 @@
__main__:1: DeprecationWarning: Using function/method
'OldAndBusted.fix_things()' is deprecated
+Removing a instance property
+----------------------------
+
+Use the :py:func:`~debtcollector.removals.removed_property` decorator
+to signal that an attribute of a class is deprecated.
+
+A basic example to do just this:
+
+.. doctest::
+
+ >>> import warnings
+ >>> warnings.simplefilter("once")
+ >>> from debtcollector import removals
+ >>> class OldAndBusted(object):
+ ... @removals.removed_property
+ ... def thing(self):
+ ... return 'old-and-busted'
+ ... @thing.setter
+ ... def thing(self, value):
+ ... pass
+ ... @thing.deleter
+ ... def thing(self):
+ ... pass
+ ...
+ >>> o = OldAndBusted()
+ >>> o.thing
+ 'old-and-busted'
+ >>> o.thing = '2'
+ >>> del o.thing
+
+.. testoutput::
+
+ __main__:1: DeprecationWarning: Reading the 'thing' property is deprecated
+ __main__:1: DeprecationWarning: Setting the 'thing' property is deprecated
+ __main__:1: DeprecationWarning: Deleting the 'thing' property is deprecated
+
Removing a keyword argument
---------------------------
@@ -113,6 +149,81 @@
__main__:1: DeprecationWarning: Using the 'bleep' argument is deprecated
+Changing the default value of a keyword argument
+------------------------------------------------
+
+A basic example to do just this:
+
+.. doctest::
+
+ >>> import warnings
+ >>> warnings.simplefilter("once")
+ >>> from debtcollector import updating
+ >>> class OldAndBusted(object):
+ ... ip = '127.0.0.1'
+ ... @updating.updated_kwarg_default_value('type', 'http', 'https')
+ ... def url(self, type='http'):
+ ... response = '%s://%s' % (type, self.ip)
+ ... return response
+ ...
+ >>> OldAndBusted().url()
+ 'http://127.0.0.1'
+
+.. testoutput::
+
+ __main__:1: FutureWarning: The http argument is changing its default value
to https, please update the code to explicitly set http as the value
+
+
+A basic classmethod example.
+
+.. note:: the @classmethod decorator is before the debtcollector one
+
+.. doctest::
+
+ >>> import warnings
+ >>> warnings.simplefilter("once")
+ >>> from debtcollector import updating
+ >>> class OldAndBusted(object):
+ ... ip = '127.0.0.1'
+ ... @classmethod
+ ... @updating.updated_kwarg_default_value('type', 'http', 'https')
+ ... def url(cls, type='http'):
+ ... response = '%s://%s' % (type, cls.ip)
+ ... return response
+ ...
+ >>> OldAndBusted.url()
+ 'http://127.0.0.1'
+
+.. testoutput::
+
+ __main__:1: FutureWarning: The http argument is changing its default value
to https, please update the code to explicitly set http as the value
+
+Moving a function
+-----------------
+
+To change the name or location of a regular function use the
+:py:func:`~debtcollector.moves.moved_function` function:
+
+.. doctest::
+
+ >>> from debtcollector import moves
+ >>> import warnings
+ >>> warnings.simplefilter('always')
+ >>> def new_thing():
+ ... return "new thing"
+ ...
+ >>> old_thing = moves.moved_function(new_thing, 'old_thing', __name__)
+ >>> new_thing()
+ 'new thing'
+ >>> old_thing()
+ 'new thing'
+
+**Expected output:**
+
+.. testoutput::
+
+ __main__:1: DeprecationWarning: Function '__main__.old_thing()' has moved
to '__main__.new_thing()'
+
Moving a method
---------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/doc/source/history.rst
new/debtcollector-1.3.0/doc/source/history.rst
--- old/debtcollector-0.8.0/doc/source/history.rst 1970-01-01
01:00:00.000000000 +0100
+++ new/debtcollector-1.3.0/doc/source/history.rst 2016-02-10
00:15:07.000000000 +0100
@@ -0,0 +1 @@
+.. include:: ../../ChangeLog
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/doc/source/index.rst
new/debtcollector-1.3.0/doc/source/index.rst
--- old/debtcollector-0.8.0/doc/source/index.rst 2015-09-08
17:29:41.000000000 +0200
+++ new/debtcollector-1.3.0/doc/source/index.rst 2016-02-10
00:15:07.000000000 +0100
@@ -12,7 +12,7 @@
project.
Contents
---------
+========
.. toctree::
:maxdepth: 2
@@ -22,6 +22,14 @@
examples
contributing
+Release Notes
+=============
+
+.. toctree::
+ :maxdepth: 1
+
+ history
+
Indices and tables
==================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/openstack-common.conf
new/debtcollector-1.3.0/openstack-common.conf
--- old/debtcollector-0.8.0/openstack-common.conf 2015-09-08
17:29:41.000000000 +0200
+++ new/debtcollector-1.3.0/openstack-common.conf 1970-01-01
01:00:00.000000000 +0100
@@ -1,6 +0,0 @@
-[DEFAULT]
-
-# The list of modules to copy from oslo-incubator.git
-
-# The base module to hold the copy of openstack.common
-base=debtcollector
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/requirements.txt
new/debtcollector-1.3.0/requirements.txt
--- old/debtcollector-0.8.0/requirements.txt 2015-09-08 17:29:41.000000000
+0200
+++ new/debtcollector-1.3.0/requirements.txt 2016-02-10 00:15:07.000000000
+0100
@@ -2,7 +2,8 @@
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
-pbr<2.0,>=1.6
-Babel>=1.3
-six>=1.9.0
+pbr>=1.6 # Apache-2.0
+Babel>=1.3 # BSD
+six>=1.9.0 # MIT
wrapt>=1.7.0 # BSD License
+funcsigs>=0.4;python_version=='2.7' or python_version=='2.6' # Apache-2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/setup.cfg
new/debtcollector-1.3.0/setup.cfg
--- old/debtcollector-0.8.0/setup.cfg 2015-09-08 17:30:03.000000000 +0200
+++ new/debtcollector-1.3.0/setup.cfg 2016-02-10 00:15:30.000000000 +0100
@@ -15,7 +15,6 @@
Programming Language :: Python
Programming Language :: Python :: 2
Programming Language :: Python :: 2.7
- Programming Language :: Python :: 2.6
Programming Language :: Python :: 3
Programming Language :: Python :: 3.3
Programming Language :: Python :: 3.4
@@ -32,11 +31,14 @@
[upload_sphinx]
upload-dir = doc/build/html
+[pbr]
+warnerrors = True
+
[wheel]
universal = 1
[egg_info]
-tag_build =
tag_svn_revision = 0
tag_date = 0
+tag_build =
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/setup.py
new/debtcollector-1.3.0/setup.py
--- old/debtcollector-0.8.0/setup.py 2015-09-08 17:29:41.000000000 +0200
+++ new/debtcollector-1.3.0/setup.py 2016-02-10 00:15:07.000000000 +0100
@@ -25,5 +25,5 @@
pass
setuptools.setup(
- setup_requires=['pbr>=1.3'],
+ setup_requires=['pbr>=1.8'],
pbr=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/test-requirements.txt
new/debtcollector-1.3.0/test-requirements.txt
--- old/debtcollector-0.8.0/test-requirements.txt 2015-09-08
17:29:41.000000000 +0200
+++ new/debtcollector-1.3.0/test-requirements.txt 2016-02-10
00:15:07.000000000 +0100
@@ -4,12 +4,14 @@
hacking<0.11,>=0.10.0
-coverage>=3.6
-discover
-python-subunit>=0.0.18
-sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2
-oslosphinx>=2.5.0 # Apache-2.0
+coverage>=3.6 # Apache-2.0
+discover # BSD
+python-subunit>=0.0.18 # Apache-2.0/BSD
+sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 # BSD
+oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0
oslotest>=1.10.0 # Apache-2.0
-testrepository>=0.0.18
-testscenarios>=0.4
-testtools>=1.4.0
+testrepository>=0.0.18 # Apache-2.0/BSD
+testscenarios>=0.4 # Apache-2.0/BSD
+testtools>=1.4.0 # MIT
+fixtures>=1.3.1 # Apache-2.0/BSD
+doc8 # Apache-2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/debtcollector-0.8.0/tox.ini
new/debtcollector-1.3.0/tox.ini
--- old/debtcollector-0.8.0/tox.ini 2015-09-08 17:29:41.000000000 +0200
+++ new/debtcollector-1.3.0/tox.ini 2016-02-10 00:15:07.000000000 +0100
@@ -1,17 +1,22 @@
[tox]
minversion = 1.6
-envlist = py33,py34,py26,py27,pypy,pep8
-skipsdist = True
+envlist = py34,py27,pypy,pep8
[testenv]
-usedevelop = True
-install_command = pip install -U {opts} {packages}
-setenv =
- VIRTUAL_ENV={envdir}
-deps = -r{toxinidir}/requirements.txt
- -r{toxinidir}/test-requirements.txt
+deps = -r{toxinidir}/test-requirements.txt
commands = python setup.py testr --slowest --testr-args='{posargs}'
+[testenv:debug]
+commands = oslo_debug_helper {posargs}
+
+[testenv:debug-py27]
+basepython = python2.7
+commands = oslo_debug_helper {posargs}
+
+[testenv:debug-py34]
+basepython = python3.4
+commands = oslo_debug_helper {posargs}
+
[testenv:pep8]
commands = flake8
@@ -26,15 +31,13 @@
[testenv:py27]
deps = {[testenv]deps}
- doc8
commands =
python setup.py testr --slowest --testr-args='{posargs}'
sphinx-build -b doctest doc/source doc/build
- doc8 doc/source
+ doc8 --ignore-path "doc/source/history.rst" doc/source
[flake8]
# E123, E125 skipped as they are invalid PEP-8.
show-source = True
ignore = E123,E125
-builtins = _
exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build