[Git][debian-gis-team/python-deprecated][upstream] New upstream version 1.2.12

Bas Couwenberg gitlab at salsa.debian.org
Sun Mar 14 05:22:41 GMT 2021



Bas Couwenberg pushed to branch upstream at Debian GIS Project / python-deprecated


Commits:
ac07d8c1 by Bas Couwenberg at 2021-03-14T06:13:48+01:00
New upstream version 1.2.12
- - - - -


15 changed files:

- .bumpversion.cfg
- .travis.yml
- CHANGELOG.rst
- deprecated/__init__.py
- deprecated/classic.py
- deprecated/sphinx.py
- docs/source/_static/banner.png
- docs/source/conf.py
- docs/source/sphinx_deco.rst
- python-deprecated.spec
- setup.py
- tests/test_sphinx.py
- tests/test_sphinx_adapter.py
- tests/test_sphinx_class.py
- tox.ini


Changes:

=====================================
.bumpversion.cfg
=====================================
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 1.2.11
+current_version = 1.2.12
 commit = True
 tag = False
 message = Prepare next version {new_version} (unreleased)
@@ -19,3 +19,4 @@ replace = release = "{new_version}"
 [bumpversion:file:python-deprecated.spec]
 search = (?<=Version:\s+){current_version}
 replace = {new_version}
+


=====================================
.travis.yml
=====================================
@@ -8,7 +8,8 @@ python:
   - "3.6"
   - "3.7"
   - "3.8"
-  - "3.9-dev"  # 3.9 development branch
+  - "3.9"
+  - "3.10-dev"  # 3.10 development branch
   - "pypy"
   - "pypy3"
 jobs:
@@ -23,7 +24,7 @@ jobs:
     python: "pypy"
     
 allow_failures:
-    - python: "3.9-dev"
+    - python: "3.10-dev"
     
 install:
   - pip install coveralls tox-travis


=====================================
CHANGELOG.rst
=====================================
@@ -18,6 +18,27 @@ and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0
       (only in comment or documentation).
 
 
+v1.2.12 (2020-03-13)
+====================
+
+Bug fix release
+
+Fix
+---
+
+- Avoid "Explicit markup ends without a blank line" when the decorated function has no docstring.
+
+- Fix #40: 'version' argument is required in Sphinx directives.
+
+- Fix #41: :mod:`deprecated.sphinx`: strip Sphinx cross-referencing syntax from warning message.
+
+
+Other
+-----
+
+- Change in Tox and Travis CI configurations: enable unit testing on Python 3.10.
+
+
 v1.2.11 (2021-01-17)
 ====================
 


=====================================
deprecated/__init__.py
=====================================
@@ -7,9 +7,9 @@ Python ``@deprecated`` decorator to deprecate old python classes, functions or m
 
 """
 
-__version__ = "1.2.11"
+__version__ = "1.2.12"
 __author__ = u"Laurent LAPORTE <tantale.solutions at gmail.com>"
-__date__ = "2021-01-17"
+__date__ = "2020-03-13"
 __credits__ = "(c) Laurent LAPORTE"
 
 from deprecated.classic import deprecated


=====================================
deprecated/classic.py
=====================================
@@ -226,7 +226,7 @@ def deprecated(*args, **kwargs):
            return x + y
 
     The *category* keyword argument allow you to specify the deprecation warning class of your choice.
-    By default, :exc:`DeprecationWarning` is ued but you can choose :exc:`FutureWarning`,
+    By default, :exc:`DeprecationWarning` is used but you can choose :exc:`FutureWarning`,
     :exc:`PendingDeprecationWarning` or a custom subclass.
 
     .. code-block:: python


=====================================
deprecated/sphinx.py
=====================================
@@ -84,6 +84,9 @@ class SphinxAdapter(ClassicAdapter):
         :param line_length:
             Max line length of the directive text. If non nul, a long text is wrapped in several lines.
         """
+        if not version:
+            # https://github.com/tantale/deprecated/issues/40
+            raise ValueError("'version' argument is required in Sphinx directives")
         self.directive = directive
         self.line_length = line_length
         super(SphinxAdapter, self).__init__(reason=reason, version=version, action=action, category=category)
@@ -119,6 +122,9 @@ class SphinxAdapter(ClassicAdapter):
         if docstring:
             # An empty line must separate the original docstring and the directive.
             docstring = re.sub(r"\n+$", "", docstring, flags=re.DOTALL) + "\n\n"
+        else:
+            # Avoid "Explicit markup ends without a blank line" when the decorated function has no docstring
+            docstring = "\n"
 
         # -- append the directive division to the docstring
         docstring += "".join("{}\n".format(line) for line in div_lines)
@@ -128,6 +134,27 @@ class SphinxAdapter(ClassicAdapter):
             return wrapped
         return super(SphinxAdapter, self).__call__(wrapped)
 
+    def get_deprecated_msg(self, wrapped, instance):
+        """
+        Get the deprecation warning message (without Sphinx cross-referencing syntax) for the user.
+
+        :param wrapped: Wrapped class or function.
+
+        :param instance: The object to which the wrapped function was bound when it was called.
+
+        :return: The warning message.
+
+        .. versionadded:: 1.2.12
+           Strip Sphinx cross-referencing syntax from warning message.
+
+        """
+        msg = super(SphinxAdapter, self).get_deprecated_msg(wrapped, instance)
+        # Strip Sphinx cross reference syntax (like ":function:", ":py:func:" and ":py:meth:")
+        # Possible values are ":role:`foo`", ":domain:role:`foo`"
+        # where ``role`` and ``domain`` should match "[a-zA-Z]+"
+        msg = re.sub(r"(?: : [a-zA-Z]+ )? : [a-zA-Z]+ : (`[^`]*`)", r"\1", msg, flags=re.X)
+        return msg
+
 
 def versionadded(reason="", version="", line_length=70):
     """


=====================================
docs/source/_static/banner.png
=====================================
Binary files a/docs/source/_static/banner.png and b/docs/source/_static/banner.png differ


=====================================
docs/source/conf.py
=====================================
@@ -61,7 +61,7 @@ author = 'Marcos CARDOSO & Laurent LAPORTE'
 # built documents.
 #
 # The full version, including alpha/beta/rc tags.
-release = "1.2.11"
+release = "1.2.12"
 # The short X.Y version.
 version = release.rpartition('.')[0]
 


=====================================
docs/source/sphinx_deco.rst
=====================================
@@ -151,6 +151,10 @@ For instance, you can configure a documentation building task in your ``tox.ini`
    commands =
        sphinx-build -b html -d {envtmpdir}/doctrees docs/source/ {envtmpdir}/html
 
+.. hint::
+
+   You can see a sample implementation of Sphinx directives in the demo project
+   `Deprecated-Demo.Sphinx <https://github.com/tantale/deprecated-demo.sphinx>`_.
 
 .. rubric:: Footnotes
 


=====================================
python-deprecated.spec
=====================================
@@ -2,7 +2,7 @@
 %global pkgname deprecated
 
 Name:           python-%{pkgname}
-Version:        1.2.11
+Version:        1.2.12
 Release:        2%{?dist}
 Summary:        Python decorator to deprecate old python classes, functions or methods
 License:        MIT


=====================================
setup.py
=====================================
@@ -143,7 +143,7 @@ from setuptools import setup
 
 setup(
     name='Deprecated',
-    version='1.2.11',
+    version='1.2.12',
     url='https://github.com/tantale/deprecated',
     project_urls={
         "Documentation": "https://deprecated.readthedocs.io/en/latest/",
@@ -178,6 +178,7 @@ setup(
         'Programming Language :: Python :: 3.7',
         'Programming Language :: Python :: 3.8',
         'Programming Language :: Python :: 3.9',
+        # 'Programming Language :: Python :: 3.10',  # scheduled on 2021-10-04
         'Topic :: Software Development :: Libraries :: Python Modules',
     ],
     extras_require={


=====================================
tests/test_sphinx.py
=====================================
@@ -24,7 +24,7 @@ import deprecated.sphinx
         :return: sum = *x* + *y*
         """,
     ],
-    ids=["no_docstring", "short_docstring", "long_docstring"]
+    ids=["no_docstring", "short_docstring", "long_docstring"],
 )
 def docstring(request):
     return request.param
@@ -44,9 +44,9 @@ def directive(request):
             '1.2.0',
             textwrap.dedent(
                 """\
-                     .. {directive}:: {version}
-                        {reason}
-                     """
+                .. {directive}:: {version}
+                   {reason}
+                """
             ),
         ),
         (
@@ -54,22 +54,12 @@ def directive(request):
             '1.2.0',
             textwrap.dedent(
                 """\
-                     .. {directive}:: {version}
-                     """
-            ),
-        ),
-        (
-            'A good reason',
-            None,
-            textwrap.dedent(
-                """\
-                     .. {directive}::
-                        {reason}
-                     """
+                .. {directive}:: {version}
+                """
             ),
         ),
     ],
-    ids=["reason&version", "version", "reason"]
+    ids=["reason&version", "version"],
 )
 def test_has_sphinx_docstring(docstring, directive, reason, version, expected):
     # The function:
@@ -90,10 +80,13 @@ def test_has_sphinx_docstring(docstring, directive, reason, version, expected):
     current = textwrap.dedent(foo.__doc__)
     assert current.endswith(expected)
 
-    # An empty line must separate the original docstring and the directive.
     current = current.replace(expected, '')
-    if current:
+    if docstring:
+        # An empty line must separate the original docstring and the directive.
         assert re.search("\n[ ]*\n$", current, flags=re.DOTALL)
+    else:
+        # Avoid "Explicit markup ends without a blank line" when the decorated function has no docstring
+        assert current == "\n"
 
     with warnings.catch_warnings(record=True) as warns:
         foo(1, 2)
@@ -118,9 +111,9 @@ def test_has_sphinx_docstring(docstring, directive, reason, version, expected):
             '1.2.0',
             textwrap.dedent(
                 """\
-                     .. {directive}:: {version}
-                        {reason}
-                     """
+                .. {directive}:: {version}
+                   {reason}
+                """
             ),
         ),
         (
@@ -128,22 +121,12 @@ def test_has_sphinx_docstring(docstring, directive, reason, version, expected):
             '1.2.0',
             textwrap.dedent(
                 """\
-                     .. {directive}:: {version}
-                     """
-            ),
-        ),
-        (
-            'A good reason',
-            None,
-            textwrap.dedent(
-                """\
-                     .. {directive}::
-                        {reason}
-                     """
+                .. {directive}:: {version}
+                """
             ),
         ),
     ],
-    ids=["reason&version", "version", "reason"]
+    ids=["reason&version", "version"],
 )
 def test_cls_has_sphinx_docstring(docstring, directive, reason, version, expected):
     # The class:
@@ -164,10 +147,13 @@ def test_cls_has_sphinx_docstring(docstring, directive, reason, version, expecte
     current = textwrap.dedent(Foo.__doc__)
     assert current.endswith(expected)
 
-    # An empty line must separate the original docstring and the directive.
     current = current.replace(expected, '')
-    if current:
+    if docstring:
+        # An empty line must separate the original docstring and the directive.
         assert re.search("\n[ ]*\n$", current, flags=re.DOTALL)
+    else:
+        # Avoid "Explicit markup ends without a blank line" when the decorated function has no docstring
+        assert current == "\n"
 
     with warnings.catch_warnings(record=True) as warns:
         Foo()
@@ -185,119 +171,71 @@ class MyDeprecationWarning(DeprecationWarning):
 
 
 _PARAMS = [
-    None,
-    ((), {}),
-    (('Good reason',), {}),
-    ((), {'reason': 'Good reason'}),
-    ((), {'version': '1.2.3'}),
-    ((), {'action': 'once'}),
-    ((), {'category': MyDeprecationWarning}),
+    {'version': '1.2.3'},
+    {'version': '1.2.3', 'reason': 'Good reason'},
+    {'version': '1.2.3', 'action': 'once'},
+    {'version': '1.2.3', 'category': MyDeprecationWarning},
 ]
 
 
 @pytest.fixture(scope="module", params=_PARAMS)
 def sphinx_deprecated_function(request):
-    if request.param is None:
-
-        @deprecated.sphinx.deprecated
-        def foo1():
-            pass
+    kwargs = request.param
 
-        return foo1
-    else:
-        args, kwargs = request.param
-
-        @deprecated.sphinx.deprecated(*args, **kwargs)
-        def foo1():
-            pass
+    @deprecated.sphinx.deprecated(**kwargs)
+    def foo1():
+        pass
 
-        return foo1
+    return foo1
 
 
 @pytest.fixture(scope="module", params=_PARAMS)
 def sphinx_deprecated_class(request):
-    if request.param is None:
+    kwargs = request.param
 
-        @deprecated.sphinx.deprecated
-        class Foo2(object):
-            pass
-
-        return Foo2
-    else:
-        args, kwargs = request.param
-
-        @deprecated.sphinx.deprecated(*args, **kwargs)
-        class Foo2(object):
-            pass
+    @deprecated.sphinx.deprecated(**kwargs)
+    class Foo2(object):
+        pass
 
-        return Foo2
+    return Foo2
 
 
 @pytest.fixture(scope="module", params=_PARAMS)
 def sphinx_deprecated_method(request):
-    if request.param is None:
-
-        class Foo3(object):
-            @deprecated.sphinx.deprecated
-            def foo3(self):
-                pass
+    kwargs = request.param
 
-        return Foo3
-    else:
-        args, kwargs = request.param
-
-        class Foo3(object):
-            @deprecated.sphinx.deprecated(*args, **kwargs)
-            def foo3(self):
-                pass
+    class Foo3(object):
+        @deprecated.sphinx.deprecated(**kwargs)
+        def foo3(self):
+            pass
 
-        return Foo3
+    return Foo3
 
 
 @pytest.fixture(scope="module", params=_PARAMS)
 def sphinx_deprecated_static_method(request):
-    if request.param is None:
-
-        class Foo4(object):
-            @staticmethod
-            @deprecated.sphinx.deprecated
-            def foo4():
-                pass
+    kwargs = request.param
 
-        return Foo4.foo4
-    else:
-        args, kwargs = request.param
-
-        class Foo4(object):
-            @staticmethod
-            @deprecated.sphinx.deprecated(*args, **kwargs)
-            def foo4():
-                pass
+    class Foo4(object):
+        @staticmethod
+        @deprecated.sphinx.deprecated(**kwargs)
+        def foo4():
+            pass
 
-        return Foo4.foo4
+    return Foo4.foo4
 
 
 @pytest.fixture(scope="module", params=_PARAMS)
 def sphinx_deprecated_class_method(request):
-    if request.param is None:
-
-        class Foo5(object):
-            @classmethod
-            @deprecated.sphinx.deprecated
-            def foo5(cls):
-                pass
+    kwargs = request.param
 
-        return Foo5
-    else:
-        args, kwargs = request.param
-
-        class Foo5(object):
-            @classmethod
-            @deprecated.sphinx.deprecated(*args, **kwargs)
-            def foo5(cls):
-                pass
+    class Foo5(object):
+        @classmethod
+        @deprecated.sphinx.deprecated(**kwargs)
+        def foo5(cls):
+            pass
 
-        return Foo5
+    return Foo5
 
 
 # noinspection PyShadowingNames
@@ -374,7 +312,7 @@ def test_should_raise_type_error():
 def test_warning_msg_has_reason():
     reason = "Good reason"
 
-    @deprecated.sphinx.deprecated(reason=reason)
+    @deprecated.sphinx.deprecated(version="4.5.6", reason=reason)
     def foo():
         pass
 
@@ -398,7 +336,7 @@ def test_warning_msg_has_version():
 
 
 def test_warning_is_ignored():
-    @deprecated.sphinx.deprecated(action='ignore')
+    @deprecated.sphinx.deprecated(version="4.5.6", action='ignore')
     def foo():
         pass
 
@@ -408,7 +346,7 @@ def test_warning_is_ignored():
 
 
 def test_specific_warning_cls_is_used():
-    @deprecated.sphinx.deprecated(category=MyDeprecationWarning)
+    @deprecated.sphinx.deprecated(version="4.5.6", category=MyDeprecationWarning)
     def foo():
         pass
 
@@ -423,3 +361,55 @@ def test_can_catch_warnings():
         warnings.simplefilter("always")
         warnings.warn("A message in a bottle", category=DeprecationWarning, stacklevel=2)
     assert len(warns) == 1
+
+
+ at pytest.mark.parametrize(
+    ["reason", "expected"],
+    [
+        ("Use :function:`bar` instead", "Use `bar` instead"),
+        ("Use :py:func:`bar` instead", "Use `bar` instead"),
+    ],
+)
+def test_sphinx_syntax_trimming(reason, expected):
+    @deprecated.sphinx.deprecated(version="4.5.6", reason=reason)
+    def foo():
+        pass
+
+    with warnings.catch_warnings(record=True) as warns:
+        foo()
+    warn = warns[0]
+    assert expected in str(warn.message)
+
+
+# noinspection SpellCheckingInspection
+ at pytest.mark.parametrize(
+    "reason, expected",
+    [
+        # classic examples using the default domain (Python)
+        ("Use :func:`bar` instead", "Use `bar` instead"),
+        ("Use :function:`bar` instead", "Use `bar` instead"),
+        ("Use :class:`Baz` instead", "Use `Baz` instead"),
+        ("Use :exc:`Baz` instead", "Use `Baz` instead"),
+        ("Use :exception:`Baz` instead", "Use `Baz` instead"),
+        ("Use :meth:`Baz.bar` instead", "Use `Baz.bar` instead"),
+        ("Use :method:`Baz.bar` instead", "Use `Baz.bar` instead"),
+        # other examples using a domain :
+        ("Use :py:func:`bar` instead", "Use `bar` instead"),
+        ("Use :cpp:func:`bar` instead", "Use `bar` instead"),
+        ("Use :js:func:`bar` instead", "Use `bar` instead"),
+        # the reference can have special characters:
+        ("Use :func:`~pkg.mod.bar` instead", "Use `~pkg.mod.bar` instead"),
+        # edge cases:
+        ("Use :r:`` instead", "Use `` instead"),
+        ("Use :d:r:`` instead", "Use `` instead"),
+        ("Use :r:`foo` instead", "Use `foo` instead"),
+        ("Use :d:r:`foo` instead", "Use `foo` instead"),
+        ("Use r:`bad` instead", "Use r:`bad` instead"),
+        ("Use ::`bad` instead", "Use ::`bad` instead"),
+        ("Use :::`bad` instead", "Use :::`bad` instead"),
+    ],
+)
+def test_get_deprecated_msg(reason, expected):
+    adapter = deprecated.sphinx.SphinxAdapter("deprecated", reason=reason, version="1")
+    actual = adapter.get_deprecated_msg(lambda: None, None)
+    assert expected in actual


=====================================
tests/test_sphinx_adapter.py
=====================================
@@ -86,7 +86,7 @@ def test_sphinx_adapter__empty_docstring(directive):
 
     wrapped = adapter.__call__(foo)
     expected = textwrap.dedent(
-        """\
+        """
         .. {directive}:: 1.2.3
            foo has changed in this version
 
@@ -117,7 +117,7 @@ def test_decorator_accept_line_length(decorator_factory, directive):
     foo = decorator(foo)
 
     expected = textwrap.dedent(
-        """\
+        """
         .. {directive}:: 1.2.3
            bar bar bar bar bar bar bar bar bar bar bar
            bar bar bar bar bar bar bar bar bar bar bar


=====================================
tests/test_sphinx_class.py
=====================================
@@ -45,7 +45,7 @@ def test_class_deprecation_using_a_simple_decorator():
     sys.version_info < (3, 3), reason="Classes should have mutable docstrings -- resolved in python 3.3"
 )
 def test_class_deprecation_using_deprecated_decorator():
-    @deprecated.sphinx.deprecated
+    @deprecated.sphinx.deprecated(version="7.8.9")
     class MyBaseClass(object):
         pass
 
@@ -66,11 +66,11 @@ def test_class_deprecation_using_deprecated_decorator():
     sys.version_info < (3, 3), reason="Classes should have mutable docstrings -- resolved in python 3.3"
 )
 def test_subclass_deprecation_using_deprecated_decorator():
-    @deprecated.sphinx.deprecated
+    @deprecated.sphinx.deprecated(version="7.8.9")
     class MyBaseClass(object):
         pass
 
-    @deprecated.sphinx.deprecated
+    @deprecated.sphinx.deprecated(version="7.8.9")
     class MySubClass(MyBaseClass):
         pass
 


=====================================
tox.ini
=====================================
@@ -11,7 +11,7 @@
 # - /usr/local/bin/pypy -> /opt/pypy2.7-v7.3.0-osx64/bin/pypy
 # - /usr/local/bin/pypy3 -> /opt/pypy3.6-v7.3.0-osx64/bin/pypy3
 envlist =
-    py{27,34,35,36,37,38,39}-wrapt{1.10,1.11,1.12}
+    py{27,34,35,36,37,38,39,310}-wrapt{1.10,1.11,1.12}
     pypy, pypy3
     docs
 
@@ -20,9 +20,9 @@ commands = pytest --cov-report term-missing --cov=deprecated tests/
 deps =
     py27,py34,py35: pip >= 9.0.3, < 19.2
     py27,py34: PyTest < 5
-    py35,py36,py37,py38,pypy,pypy3: PyTest
+    py35,py36,py37,py38,py39,pypy,pypy3: PyTest
     py27,py34: PyTest-Cov < 2.6
-    py35,py36,py37,py38,py39,pypy,pypy3: PyTest-Cov
+    py35,py36,py37,py38,py39,py310,pypy,pypy3: PyTest-Cov
     wrapt1.10: wrapt ~= 1.10.0
     wrapt1.11: wrapt ~= 1.11.0
     wrapt1.12: wrapt ~= 1.12.0



View it on GitLab: https://salsa.debian.org/debian-gis-team/python-deprecated/-/commit/ac07d8c1fbe7286cec512ee686e7f43f8a5c9c07

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/python-deprecated/-/commit/ac07d8c1fbe7286cec512ee686e7f43f8a5c9c07
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20210314/fea29386/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list