[Git][debian-gis-team/python-deprecated][master] 5 commits: New upstream version 1.2.15
Bas Couwenberg (@sebastic)
gitlab at salsa.debian.org
Sat Nov 16 05:47:23 GMT 2024
Bas Couwenberg pushed to branch master at Debian GIS Project / python-deprecated
Commits:
1c009c37 by Bas Couwenberg at 2024-11-16T06:40:16+01:00
New upstream version 1.2.15
- - - - -
da3eaac4 by Bas Couwenberg at 2024-11-16T06:40:20+01:00
Update upstream source from tag 'upstream/1.2.15'
Update to upstream version '1.2.15'
with Debian dir c76207b12885f7d21818af2dfa44eddae1d2c95e
- - - - -
db720821 by Bas Couwenberg at 2024-11-16T06:40:32+01:00
New upstream release.
- - - - -
9a01320b by Bas Couwenberg at 2024-11-16T06:43:04+01:00
Drop patches, applied/fixed upstream.
- - - - -
7b4fa1e3 by Bas Couwenberg at 2024-11-16T06:43:20+01:00
Set distribution to unstable.
- - - - -
29 changed files:
- .bumpversion.cfg
- .github/CODE_OF_CONDUCT.md
- .github/workflows/codeql-analysis.yml
- .github/workflows/python-package.yml
- .gitignore
- − .travis.yml
- CHANGELOG.rst
- CONTRIBUTING.rst
- README.md
- − appveyor.yml
- debian/changelog
- − debian/patches/pr73-python3.13.patch
- − debian/patches/python3.13-pytest.patch
- − debian/patches/series
- deprecated/__init__.py
- deprecated/classic.py
- deprecated/sphinx.py
- docs/source/conf.py
- docs/source/installation.rst
- docs/source/introduction.rst
- docs/source/tutorial.rst
- + docs/source/tutorial/warning_ctrl/extra_stacklevel_demo.py
- docs/source/white_paper.rst
- python-deprecated.spec
- setup.py
- tests/test_deprecated.py
- tests/test_sphinx.py
- tests/test_sphinx_class.py
- tox.ini
Changes:
=====================================
.bumpversion.cfg
=====================================
@@ -1,16 +1,12 @@
[bumpversion]
-current_version = 1.2.14
+current_version = 1.2.15
commit = True
tag = False
message = Prepare next version {new_version} (unreleased)
[bumpversion:file:setup.py]
-search = version='{current_version}'
-replace = version='{new_version}'
-
-[bumpversion:file:appveyor.yml]
-search = version: {current_version}
-replace = version: {new_version}
+search = version="{current_version}"
+replace = version="{new_version}"
[bumpversion:file:deprecated/__init__.py]
search = __version__ = "{current_version}"
=====================================
.github/CODE_OF_CONDUCT.md
=====================================
@@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
-reported by contacting the project team at [Tantale Solutions](mailto:tantale.solutions at gmail.com). All
+reported by contacting the project team at [Laurent LAPORTE](mailto:laurent.laporte.pro at gmail.com). All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
=====================================
.github/workflows/codeql-analysis.yml
=====================================
@@ -39,7 +39,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout at v3
+ uses: actions/checkout at v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
=====================================
.github/workflows/python-package.yml
=====================================
@@ -12,22 +12,26 @@ on:
jobs:
pytest:
strategy:
+ fail-fast: false
matrix:
platform: [ ubuntu-latest, macos-latest, windows-latest ]
- python-version: [ "3.7", "3.8", "3.9", "3.10", "3.11" ]
+ python-version: [ "3.7", "3.8", "3.9", "3.10", "3.11", "3.12" ]
+ exclude:
+ - platform: macos-latest
+ python-version: "3.7"
runs-on: ${{ matrix.platform }}
steps:
- - uses: actions/checkout at v3
+ - uses: actions/checkout at v4
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python at v4
+ uses: actions/setup-python at v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
- python -m pip install 'PyTest'
+ python -m pip install pytest setuptools
python -m pip install -e .
- name: Test with pytest
run: |
=====================================
.gitignore
=====================================
@@ -1,160 +1,4 @@
-
-# Created by https://www.gitignore.io/api/intellij,linux,osx,pycharm,python
-
-### Intellij ###
-# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
-# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
-
-# User-specific stuff:
-.idea/
-.idea/workspace.xml
-.idea/tasks.xml
-.idea/dictionaries
-.idea/vcs.xml
-.idea/jsLibraryMappings.xml
-
-# Sensitive or high-churn files:
-.idea/dataSources.ids
-.idea/dataSources.xml
-.idea/dataSources.local.xml
-.idea/sqlDataSources.xml
-.idea/dynamic.xml
-.idea/uiDesigner.xml
-
-# Gradle:
-.idea/gradle.xml
-.idea/libraries
-
-# Mongo Explorer plugin:
-.idea/mongoSettings.xml
-
-## File-based project format:
-*.iws
-
-## Plugin-specific files:
-
-# IntelliJ
-/out/
-
-# mpeltonen/sbt-idea plugin
-.idea_modules/
-
-# JIRA plugin
-atlassian-ide-plugin.xml
-
-# Crashlytics plugin (for Android Studio and IntelliJ)
-com_crashlytics_export_strings.xml
-crashlytics.properties
-crashlytics-build.properties
-fabric.properties
-
-### Intellij Patch ###
-# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
-
-# *.iml
-# modules.xml
-# .idea/misc.xml
-# *.ipr
-
-
-### Linux ###
-*~
-
-# temporary files which can be created if a process still has a handle open of a deleted file
-.fuse_hidden*
-
-# KDE directory preferences
-.directory
-
-# Linux trash folder which might appear on any partition or disk
-.Trash-*
-
-
-### OSX ###
-*.DS_Store
-.AppleDouble
-.LSOverride
-
-# Icon must end with two \r
-Icon
-
-
-# Thumbnails
-._*
-
-# Files that might appear in the root of a volume
-.DocumentRevisions-V100
-.fseventsd
-.Spotlight-V100
-.TemporaryItems
-.Trashes
-.VolumeIcon.icns
-.com.apple.timemachine.donotpresent
-
-# Directories potentially created on remote AFP share
-.AppleDB
-.AppleDesktop
-Network Trash Folder
-Temporary Items
-.apdisk
-
-
-### PyCharm ###
-# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
-# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
-
-# User-specific stuff:
-.idea/workspace.xml
-.idea/tasks.xml
-.idea/dictionaries
-.idea/vcs.xml
-.idea/jsLibraryMappings.xml
-
-# Sensitive or high-churn files:
-.idea/dataSources.ids
-.idea/dataSources.xml
-.idea/dataSources.local.xml
-.idea/sqlDataSources.xml
-.idea/dynamic.xml
-.idea/uiDesigner.xml
-
-# Gradle:
-.idea/gradle.xml
-.idea/libraries
-
-# Mongo Explorer plugin:
-.idea/mongoSettings.xml
-
-## File-based project format:
-*.iws
-
-## Plugin-specific files:
-
-# IntelliJ
-/out/
-
-# mpeltonen/sbt-idea plugin
-.idea_modules/
-
-# JIRA plugin
-atlassian-ide-plugin.xml
-
-# Crashlytics plugin (for Android Studio and IntelliJ)
-com_crashlytics_export_strings.xml
-crashlytics.properties
-crashlytics-build.properties
-fabric.properties
-
-### PyCharm Patch ###
-# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
-
-# *.iml
-# modules.xml
-# .idea/misc.xml
-# *.ipr
-
-
-### Python ###
+### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
@@ -165,7 +9,6 @@ __pycache__/
# Distribution / packaging
.Python
-env/
build/
develop-eggs/
dist/
@@ -177,14 +20,18 @@ lib64/
parts/
sdist/
var/
+wheels/
+share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
+MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
+*.spec
# Installer logs
pip-log.txt
@@ -193,13 +40,17 @@ pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
+.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
-*,cover
+*.cover
+*.py,cover
.hypothesis/
+.pytest_cache/
+cover/
# Translations
*.mo
@@ -208,6 +59,8 @@ coverage.xml
# Django stuff:
*.log
local_settings.py
+db.sqlite3
+db.sqlite3-journal
# Flask stuff:
instance/
@@ -220,27 +73,91 @@ instance/
docs/_build/
# PyBuilder
+.pybuilder/
target/
-# IPython Notebook
+# Jupyter Notebook
.ipynb_checkpoints
-# pyenv
-.python-version
+# IPython
+profile_default/
+ipython_config.py
-# celery beat schedule file
+# pyenv
+# For a library or package, you might want to ignore these files since the code is
+# intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# poetry
+# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
+# This is especially recommended for binary packages to ensure reproducibility, and is more
+# commonly ignored for libraries.
+# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
+#poetry.lock
+
+# pdm
+# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
+#pdm.lock
+# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
+# in version control.
+# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
+.pdm.toml
+.pdm-python
+.pdm-build/
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
+__pypackages__/
+
+# Celery stuff
celerybeat-schedule
+celerybeat.pid
-# dotenv
-.env
+# SageMath parsed files
+*.sage.py
-# virtualenv
+# Environments
+.env
+.venv
+env/
venv/
ENV/
+env.bak/
+venv.bak/
# Spyder project settings
.spyderproject
+.spyproject
# Rope project settings
.ropeproject
-.pytest_cache/
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+# PyCharm
+# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
+# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
+# and can be added to the global gitignore or merged into this file. For a more nuclear
+# option (not recommended) you can uncomment the following to ignore the entire idea folder.
+.idea/
=====================================
.travis.yml deleted
=====================================
@@ -1,27 +0,0 @@
-dist: focal
-arch:
- - amd64
- - ppc64le
-language: python
-python:
- - "3.7"
- - "3.8"
- - "3.9"
- - "3.10"
- - "3.11"
- - "3.12-dev" # development branch
- - "pypy3.9-7.3.9"
-jobs:
- exclude:
- - arch: ppc64le
- python: "pypy3.9-7.3.9"
-
-allow_failures:
- - python: "3.12-dev"
-
-install:
- - pip install coveralls tox-travis
-script:
- tox
-after_success:
- coveralls
=====================================
CHANGELOG.rst
=====================================
@@ -18,7 +18,29 @@ and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0
(only in comment or documentation).
-v1.2.14 (unreleased)
+v1.2.15 (2024-11-15)
+====================
+
+Bug fix release
+
+Fix
+---
+
+- Resolve Python 2.7 support issue introduced in v1.2.14 in ``sphinx.py``.
+
+- Fix #69: Add ``extra_stacklevel`` argument for interoperating with other wrapper functions (refer to #68 for a concrete use case).
+
+- Fix #73: Update class method deprecation warnings for Python 3.13.
+
+- Fix #75: Update GitHub workflows and fix development dependencies for Python 3.12.
+
+Other
+-----
+
+- Fix #66: discontinue TravisCI and AppVeyor due to end of free support.
+
+
+v1.2.14 (2023-05-27)
====================
Bug fix release
@@ -64,7 +86,7 @@ Other
+ install ``typing`` when building on Python 3.4 (required by Pytest->Attrs).
+ run unit tests on Wrapt 1.13 (release candidate).
-- Migrating project to `travis-ci.com <https://travis-ci.com/github/tantale/deprecated>`_.
+- Migrating project to `travis-ci.com <https://www.travis-ci.com/github/tantale/deprecated>`_.
v1.2.12 (2021-03-13)
@@ -146,7 +168,7 @@ Bug fix release
Fix
---
-- Fix #20: Set the :func:`warnings.warn` stacklevel to 2 if the Python implementation is `PyPy <https://www.pypy.org/>`_.
+- Fix #20: Set the :func:`warnings.warn` stacklevel to 2 if the Python implementation is `PyPy <https://pypy.org/>`_.
- Fix packit configuration: use ``dist-git-branch: fedora-all``.
@@ -449,7 +471,7 @@ Added
Other
-----
-- Improve `Travis <https://travis-ci.com/>`_ configuration file (compatibility from Python 2.6 to 3.7-dev, and PyPy).
+- Improve `Travis <https://www.travis-ci.com/>`_ configuration file (compatibility from Python 2.6 to 3.7-dev, and PyPy).
- Add `AppVeyor <https://www.appveyor.com/docs/>`_ configuration file.
- Add `Tox <https://tox.readthedocs.io/en/latest/>`_ configuration file.
- Add `BumpVersion <https://github.com/peritus/bumpversion>`_ configuration file.
=====================================
CONTRIBUTING.rst
=====================================
@@ -55,8 +55,8 @@ First time setup
- Add the main repository as a remote to update later::
- git remote add tantale https://github.com/tantale/deprecated.git
- git fetch tantale
+ git remote add upstream https://github.com/laurent-laporte-pro/deprecated.git
+ git fetch upstream
- Create a virtualenv::
@@ -72,7 +72,7 @@ First time setup
.. _latest version of git: https://git-scm.com/downloads
.. _username: https://help.github.com/articles/setting-your-username-in-git/
.. _email: https://help.github.com/articles/setting-your-commit-email-address-in-git/
-.. _Fork: https://github.com/tantale/deprecated#fork-destination-box
+.. _Fork: https://github.com/laurent-laporte-pro/deprecated#fork-destination-box
.. _Clone: https://help.github.com/articles/fork-a-repo/#step-2-create-a-local-clone-of-your-fork
Start coding
=====================================
README.md
=====================================
@@ -2,12 +2,14 @@
Python ``@deprecated`` decorator to deprecate old python classes, functions or methods.
-[](https://travis-ci.com/tantale/deprecated)
-[](https://ci.appveyor.com/project/tantale/deprecated)
-[](https://coveralls.io/github/tantale/deprecated?branch=master)
-[](https://badge.fury.io/gh/tantale%2Fdeprecated)
-[](https://raw.githubusercontent.com/tantale/deprecated/master/LICENSE.rst)
-[](http://deprecated.readthedocs.io/en/latest/?badge=latest)
+
+[](https://raw.githubusercontent.com/laurent-laporte-pro/deprecated/master/LICENSE.rst)
+[](https://github.com/laurent-laporte-pro/deprecated/releases/latest)
+[](https://pypi.org/project/Deprecated/)
+[](https://github.com/laurent-laporte-pro/deprecated/actions/workflows/python-package.yml)
+[](https://coveralls.io/github/laurent-laporte-pro/deprecated?branch=master)
+[
+](http://deprecated.readthedocs.io/en/latest/?badge=latest)
## Installation
@@ -60,7 +62,7 @@ def some_old_function(x, y):
The authors of this library are:
[Marcos CARDOSO](https://github.com/vrcmarcos), and
-[Laurent LAPORTE](https://github.com/tantale).
+[Laurent LAPORTE](https://github.com/laurent-laporte-pro).
The original code was made in [this StackOverflow post](https://stackoverflow.com/questions/2536307) by
[Leandro REGUEIRO](https://stackoverflow.com/users/1336250/leandro-regueiro),
=====================================
appveyor.yml deleted
=====================================
@@ -1,60 +0,0 @@
-# Deprecated's package version, sync with setup.py
-version: 1.2.14.{build}
-# Explicitly set base image to use
-image: Visual Studio 2022
-
-environment:
- matrix:
- # What Python version is installed where:
- # https://www.appveyor.com/docs/windows-images-software/#python
- - PYTHON: "C:\\Python37"
- TOX_ENV: "py37"
-
- - PYTHON: "C:\\Python37-x64"
- TOX_ENV: "py37"
-
- - PYTHON: "C:\\Python38"
- TOX_ENV: "py38"
-
- - PYTHON: "C:\\Python38-x64"
- TOX_ENV: "py38"
-
- - PYTHON: "C:\\Python39"
- TOX_ENV: "py39"
-
- - PYTHON: "C:\\Python39-x64"
- TOX_ENV: "py39"
-
- - PYTHON: "C:\\Python310"
- TOX_ENV: "py310"
-
- - PYTHON: "C:\\Python310-x64"
- TOX_ENV: "py310"
-
- - PYTHON: "C:\\Python311"
- TOX_ENV: "py311"
-
- - PYTHON: "C:\\Python311-x64"
- TOX_ENV: "py311"
-
-init:
- - set PATH=%PYTHON%;%PYTHON%\Scripts;C:\MinGW\msys\1.0\bin;%PATH%
- - "git config --system http.sslcainfo \"C:\\Program Files\\Git\\mingw64\\ssl\\certs\\ca-bundle.crt\""
- - "%PYTHON%\\python.exe -V"
- - "%PYTHON%\\python.exe -c \"import struct;print(8 * struct.calcsize(\'P\'))\""
-
-install:
- - "%PYTHON%\\python.exe -m pip install wheel"
- - "%PYTHON%\\python.exe -m pip install tox"
-
-build: false # Not a C# project, build stuff at the test step instead.
-
-test_script:
- - "%PYTHON%\\Scripts\\tox.exe -e %TOX_ENV%"
-
-after_test:
- - "%PYTHON%\\python.exe setup.py --command-packages wheel bdist_wheel"
- - ps: "ls dist"
-
-artifacts:
- - path: dist\*
=====================================
debian/changelog
=====================================
@@ -1,3 +1,10 @@
+python-deprecated (1.2.15-1) unstable; urgency=medium
+
+ * New upstream release.
+ * Drop patches, applied/fixed upstream.
+
+ -- Bas Couwenberg <sebastic at debian.org> Sat, 16 Nov 2024 06:43:07 +0100
+
python-deprecated (1.2.14-2) unstable; urgency=medium
* Bump debhelper compat to 13.
=====================================
debian/patches/pr73-python3.13.patch deleted
=====================================
@@ -1,32 +0,0 @@
-Description: Update class method deprecation warnings for Python 3.13
- Update the version range for modified deprecation warnings that was
- introduced in efb3e60623e1dda88c2725a93223d290924e8666, since Python
- 3.13 reverted the change originally introduced in 3.9 and is back to
- the old messages. This fixes tests with Python 3.13.
- .
- See also https://github.com/GrahamDumpleton/wrapt/pull/260.
-Author: Michał Górny <mgorny at gentoo.org>
-Bug: https://github.com/laurent-laporte-pro/deprecated/pull/73
-
---- a/tests/test_deprecated.py
-+++ b/tests/test_deprecated.py
-@@ -185,7 +185,7 @@ def test_classic_deprecated_class_method
- assert len(warns) == 1
- warn = warns[0]
- assert issubclass(warn.category, DeprecationWarning)
-- if sys.version_info >= (3, 9):
-+ if (3, 9) <= sys.version_info < (3, 13):
- assert "deprecated class method" in str(warn.message)
- else:
- assert "deprecated function (or staticmethod)" in str(warn.message)
---- a/tests/test_sphinx.py
-+++ b/tests/test_sphinx.py
-@@ -301,7 +301,7 @@ def test_sphinx_deprecated_class_method_
- assert len(warns) == 1
- warn = warns[0]
- assert issubclass(warn.category, DeprecationWarning)
-- if sys.version_info >= (3, 9):
-+ if (3, 9) <= sys.version_info < (3, 13):
- assert "deprecated class method" in str(warn.message)
- else:
- assert "deprecated function (or staticmethod)" in str(warn.message)
=====================================
debian/patches/python3.13-pytest.patch deleted
=====================================
@@ -1,15 +0,0 @@
-Description: Fix FTBFS with Python 3.13.
-Author: Bas Couwenberg <sebastic at debian.org>
-Forwarded: not-needed
-
---- a/tests/test_deprecated.py
-+++ b/tests/test_deprecated.py
-@@ -148,7 +148,7 @@ def test_classic_deprecated_class__warns
- warn = warns[0]
- assert issubclass(warn.category, DeprecationWarning)
- assert "deprecated class" in str(warn.message)
-- assert warn.filename == __file__, 'Incorrect warning stackLevel'
-+# assert warn.filename == __file__, 'Incorrect warning stackLevel'
-
-
- # noinspection PyShadowingNames
=====================================
debian/patches/series deleted
=====================================
@@ -1,2 +0,0 @@
-pr73-python3.13.patch
-python3.13-pytest.patch
=====================================
deprecated/__init__.py
=====================================
@@ -7,9 +7,9 @@ Python ``@deprecated`` decorator to deprecate old python classes, functions or m
"""
-__version__ = "1.2.14"
-__author__ = u"Laurent LAPORTE <tantale.solutions at gmail.com>"
-__date__ = "unreleased"
+__version__ = "1.2.15"
+__author__ = u"Laurent LAPORTE <laurent.laporte.pro at gmail.com>"
+__date__ = "2024-11-15"
__credits__ = "(c) Laurent LAPORTE"
from deprecated.classic import deprecated
=====================================
deprecated/classic.py
=====================================
@@ -17,7 +17,7 @@ import wrapt
try:
# If the C extension for wrapt was compiled and wrapt/_wrappers.pyd exists, then the
# stack level that should be passed to warnings.warn should be 2. However, if using
- # a pure python wrapt, a extra stacklevel is required.
+ # a pure python wrapt, an extra stacklevel is required.
import wrapt._wrappers
_routine_stacklevel = 2
@@ -83,7 +83,7 @@ class ClassicAdapter(wrapt.AdapterFactory):
return x + y
"""
- def __init__(self, reason="", version="", action=None, category=DeprecationWarning):
+ def __init__(self, reason="", version="", action=None, category=DeprecationWarning, extra_stacklevel=0):
"""
Construct a wrapper adapter.
@@ -97,23 +97,33 @@ class ClassicAdapter(wrapt.AdapterFactory):
If you follow the `Semantic Versioning <https://semver.org/>`_,
the version number has the format "MAJOR.MINOR.PATCH".
- :type action: str
+ :type action: Literal["default", "error", "ignore", "always", "module", "once"]
:param action:
A warning filter used to activate or not the deprecation warning.
Can be one of "error", "ignore", "always", "default", "module", or "once".
- If ``None`` or empty, the the global filtering mechanism is used.
+ If ``None`` or empty, the global filtering mechanism is used.
See: `The Warnings Filter`_ in the Python documentation.
- :type category: type
+ :type category: Type[Warning]
:param category:
The warning category to use for the deprecation warning.
By default, the category class is :class:`~DeprecationWarning`,
you can inherit this class to define your own deprecation warning category.
+
+ :type extra_stacklevel: int
+ :param extra_stacklevel:
+ Number of additional stack levels to consider instrumentation rather than user code.
+ With the default value of 0, the warning refers to where the class was instantiated
+ or the function was called.
+
+ .. versionchanged:: 1.2.15
+ Add the *extra_stacklevel* parameter.
"""
self.reason = reason or ""
self.version = version or ""
self.action = action
self.category = category
+ self.extra_stacklevel = extra_stacklevel
super(ClassicAdapter, self).__init__()
def get_deprecated_msg(self, wrapped, instance):
@@ -161,12 +171,13 @@ class ClassicAdapter(wrapt.AdapterFactory):
def wrapped_cls(cls, *args, **kwargs):
msg = self.get_deprecated_msg(wrapped, None)
+ stacklevel = _class_stacklevel + self.extra_stacklevel
if self.action:
with warnings.catch_warnings():
warnings.simplefilter(self.action, self.category)
- warnings.warn(msg, category=self.category, stacklevel=_class_stacklevel)
+ warnings.warn(msg, category=self.category, stacklevel=stacklevel)
else:
- warnings.warn(msg, category=self.category, stacklevel=_class_stacklevel)
+ warnings.warn(msg, category=self.category, stacklevel=stacklevel)
if old_new1 is object.__new__:
return old_new1(cls)
# actually, we don't know the real signature of *old_new1*
@@ -174,6 +185,24 @@ class ClassicAdapter(wrapt.AdapterFactory):
wrapped.__new__ = staticmethod(wrapped_cls)
+ elif inspect.isroutine(wrapped):
+ @wrapt.decorator
+ def wrapper_function(wrapped_, instance_, args_, kwargs_):
+ msg = self.get_deprecated_msg(wrapped_, instance_)
+ stacklevel = _routine_stacklevel + self.extra_stacklevel
+ if self.action:
+ with warnings.catch_warnings():
+ warnings.simplefilter(self.action, self.category)
+ warnings.warn(msg, category=self.category, stacklevel=stacklevel)
+ else:
+ warnings.warn(msg, category=self.category, stacklevel=stacklevel)
+ return wrapped_(*args_, **kwargs_)
+
+ return wrapper_function(wrapped)
+
+ else:
+ raise TypeError(repr(type(wrapped)))
+
return wrapped
@@ -226,7 +255,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 used 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
@@ -240,7 +269,7 @@ def deprecated(*args, **kwargs):
The *action* keyword argument allow you to locally change the warning filtering.
*action* can be one of "error", "ignore", "always", "default", "module", or "once".
- If ``None``, empty or missing, the the global filtering mechanism is used.
+ If ``None``, empty or missing, the global filtering mechanism is used.
See: `The Warnings Filter`_ in the Python documentation.
.. code-block:: python
@@ -252,6 +281,9 @@ def deprecated(*args, **kwargs):
def some_old_function(x, y):
return x + y
+ The *extra_stacklevel* keyword argument allows you to specify additional stack levels
+ to consider instrumentation rather than user code. With the default value of 0, the
+ warning refers to where the class was instantiated or the function was called.
"""
if args and isinstance(args[0], string_types):
kwargs['reason'] = args[0]
@@ -261,32 +293,9 @@ def deprecated(*args, **kwargs):
raise TypeError(repr(type(args[0])))
if args:
- action = kwargs.get('action')
- category = kwargs.get('category', DeprecationWarning)
adapter_cls = kwargs.pop('adapter_cls', ClassicAdapter)
adapter = adapter_cls(**kwargs)
-
wrapped = args[0]
- if inspect.isclass(wrapped):
- wrapped = adapter(wrapped)
- return wrapped
-
- elif inspect.isroutine(wrapped):
-
- @wrapt.decorator(adapter=adapter)
- def wrapper_function(wrapped_, instance_, args_, kwargs_):
- msg = adapter.get_deprecated_msg(wrapped_, instance_)
- if action:
- with warnings.catch_warnings():
- warnings.simplefilter(action, category)
- warnings.warn(msg, category=category, stacklevel=_routine_stacklevel)
- else:
- warnings.warn(msg, category=category, stacklevel=_routine_stacklevel)
- return wrapped_(*args_, **kwargs_)
-
- return wrapper_function(wrapped)
-
- else:
- raise TypeError(repr(type(wrapped)))
+ return adapter(wrapped)
return functools.partial(deprecated, **kwargs)
=====================================
deprecated/sphinx.py
=====================================
@@ -22,8 +22,6 @@ when the function/method is called or the class is constructed.
import re
import textwrap
-import wrapt
-
from deprecated.classic import ClassicAdapter
from deprecated.classic import deprecated as _classic_deprecated
@@ -48,6 +46,7 @@ class SphinxAdapter(ClassicAdapter):
version="",
action=None,
category=DeprecationWarning,
+ extra_stacklevel=0,
line_length=70,
):
"""
@@ -67,29 +66,40 @@ class SphinxAdapter(ClassicAdapter):
If you follow the `Semantic Versioning <https://semver.org/>`_,
the version number has the format "MAJOR.MINOR.PATCH".
- :type action: str
+ :type action: Literal["default", "error", "ignore", "always", "module", "once"]
:param action:
A warning filter used to activate or not the deprecation warning.
Can be one of "error", "ignore", "always", "default", "module", or "once".
- If ``None`` or empty, the the global filtering mechanism is used.
+ If ``None`` or empty, the global filtering mechanism is used.
See: `The Warnings Filter`_ in the Python documentation.
- :type category: type
+ :type category: Type[Warning]
:param category:
The warning category to use for the deprecation warning.
By default, the category class is :class:`~DeprecationWarning`,
you can inherit this class to define your own deprecation warning category.
+ :type extra_stacklevel: int
+ :param extra_stacklevel:
+ Number of additional stack levels to consider instrumentation rather than user code.
+ With the default value of 0, the warning refers to where the class was instantiated
+ or the function was called.
+
:type line_length: int
:param line_length:
Max line length of the directive text. If non nul, a long text is wrapped in several lines.
+
+ .. versionchanged:: 1.2.15
+ Add the *extra_stacklevel* parameter.
"""
if not version:
- # https://github.com/tantale/deprecated/issues/40
+ # https://github.com/laurent-laporte-pro/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)
+ super(SphinxAdapter, self).__init__(
+ reason=reason, version=version, action=action, category=category, extra_stacklevel=extra_stacklevel
+ )
def __call__(self, wrapped):
"""
@@ -102,7 +112,7 @@ class SphinxAdapter(ClassicAdapter):
# -- build the directive division
fmt = ".. {directive}:: {version}" if self.version else ".. {directive}::"
div_lines = [fmt.format(directive=self.directive, version=self.version)]
- width = self.line_length - 3 if self.line_length > 3 else 2 ** 16
+ width = self.line_length - 3 if self.line_length > 3 else 2**16
reason = textwrap.dedent(self.reason).strip()
for paragraph in reason.splitlines():
if paragraph:
@@ -120,7 +130,7 @@ class SphinxAdapter(ClassicAdapter):
# -- get the docstring, normalize the trailing newlines
# keep a consistent behaviour if the docstring starts with newline or directly on the first one
docstring = wrapped.__doc__ or ""
- lines = docstring.splitlines(keepends=True) or [""]
+ lines = docstring.splitlines(True) or [""]
docstring = textwrap.dedent("".join(lines[1:])) if len(lines) > 1 else ""
docstring = lines[0] + docstring
if docstring:
@@ -153,7 +163,7 @@ class SphinxAdapter(ClassicAdapter):
"""
msg = super(SphinxAdapter, self).get_deprecated_msg(wrapped, instance)
- # Strip Sphinx cross reference syntax (like ":function:", ":py:func:" and ":py:meth:")
+ # 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)
@@ -163,7 +173,7 @@ class SphinxAdapter(ClassicAdapter):
def versionadded(reason="", version="", line_length=70):
"""
This decorator can be used to insert a "versionadded" directive
- in your function/class docstring in order to documents the
+ in your function/class docstring in order to document the
version of the project which adds this new functionality in your library.
:param str reason:
@@ -193,7 +203,7 @@ def versionadded(reason="", version="", line_length=70):
def versionchanged(reason="", version="", line_length=70):
"""
This decorator can be used to insert a "versionchanged" directive
- in your function/class docstring in order to documents the
+ in your function/class docstring in order to document the
version of the project which modifies this functionality in your library.
:param str reason:
@@ -222,7 +232,7 @@ def versionchanged(reason="", version="", line_length=70):
def deprecated(reason="", version="", line_length=70, **kwargs):
"""
This decorator can be used to insert a "deprecated" directive
- in your function/class docstring in order to documents the
+ in your function/class docstring in order to document the
version of the project which deprecates this functionality in your library.
:param str reason:
@@ -242,17 +252,26 @@ def deprecated(reason="", version="", line_length=70, **kwargs):
- "action":
A warning filter used to activate or not the deprecation warning.
Can be one of "error", "ignore", "always", "default", "module", or "once".
- If ``None``, empty or missing, the the global filtering mechanism is used.
+ If ``None``, empty or missing, the global filtering mechanism is used.
- "category":
The warning category to use for the deprecation warning.
By default, the category class is :class:`~DeprecationWarning`,
you can inherit this class to define your own deprecation warning category.
+ - "extra_stacklevel":
+ Number of additional stack levels to consider instrumentation rather than user code.
+ With the default value of 0, the warning refers to where the class was instantiated
+ or the function was called.
+
+
:return: a decorator used to deprecate a function.
.. versionchanged:: 1.2.13
Change the signature of the decorator to reflect the valid use cases.
+
+ .. versionchanged:: 1.2.15
+ Add the *extra_stacklevel* parameter.
"""
directive = kwargs.pop('directive', 'deprecated')
adapter_cls = kwargs.pop('adapter_cls', SphinxAdapter)
=====================================
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.14"
+release = "1.2.15"
# The short X.Y version.
version = release.rpartition('.')[0]
=====================================
docs/source/installation.rst
=====================================
@@ -127,7 +127,7 @@ update the code from the master branch:
.. code-block:: sh
- pip install -U https://github.com/tantale/deprecated/archive/master.tar.gz
+ pip install -U https://github.com/laurent-laporte-pro/deprecated/archive/master.tar.gz
.. _install-install-virtualenv:
=====================================
docs/source/introduction.rst
=====================================
@@ -4,7 +4,7 @@ Introduction
What "Deprecated" Means
-----------------------
-.. _Deprecated Library: https://pypi.python.org/pypi/deprecated
+.. _Deprecated Library: https://pypi.org/project/Deprecated/
A function or class is deprecated when it is considered as it is no longer important. It is so unimportant, in fact, that you should no longer use it, since it has been superseded and may cease to exist in the future.
=====================================
docs/source/tutorial.rst
=====================================
@@ -127,7 +127,7 @@ Controlling warnings
--------------------
.. _Python warning control: https://docs.python.org/3/library/warnings.html
-.. _-W: https://docs.python.org/3/using/cmdline.html#cmdoption-w
+.. _-W: https://docs.python.org/3/using/cmdline.html#cmdoption-W
.. _PYTHONWARNINGS: https://docs.python.org/3/using/cmdline.html#envvar-PYTHONWARNINGS
Warnings are emitted using the `Python warning control`_. By default, Python installs several warning filters,
@@ -242,3 +242,28 @@ function will raise an exception because the *action* is set to "error".
File "path/to/deprecated/classic.py", line 274, in wrapper_function
warnings.warn(msg, category=category, stacklevel=_stacklevel)
DeprecationWarning: Call to deprecated function (or staticmethod) foo. (do not call it)
+
+
+Modifying the deprecated code reference
+---------------------------------------
+
+By default, when a deprecated function or class is called, the warning message indicates the location of the caller.
+
+The ``extra_stacklevel`` parameter allows customizing the stack level reference in the deprecation warning message.
+
+This parameter is particularly useful in scenarios where you have a factory or utility function that creates deprecated
+objects or performs deprecated operations. By specifying an ``extra_stacklevel`` value, you can control the stack level
+at which the deprecation warning is emitted, making it appear as if the calling function is the deprecated one,
+rather than the actual deprecated entity.
+
+For example, if you have a factory function ``create_object()`` that creates deprecated objects, you can use
+the ``extra_stacklevel`` parameter to emit the deprecation warning at the calling location. This provides clearer and
+more actionable deprecation messages, allowing developers to identify and update the code that invokes the deprecated
+functionality.
+
+For instance:
+
+.. literalinclude:: tutorial/warning_ctrl/extra_stacklevel_demo.py
+
+Please note that the ``extra_stacklevel`` value should be an integer indicating the number of stack levels to skip
+when emitting the deprecation warning.
=====================================
docs/source/tutorial/warning_ctrl/extra_stacklevel_demo.py
=====================================
@@ -0,0 +1,24 @@
+import warnings
+
+from deprecated import deprecated
+
+
+ at deprecated(version='1.0', extra_stacklevel=1)
+class MyObject(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __str__(self):
+ return "object: {name}".format(name=self.name)
+
+
+def create_object(name):
+ return MyObject(name)
+
+
+if __name__ == '__main__':
+ warnings.filterwarnings("default", category=DeprecationWarning)
+ # warn here:
+ print(create_object("orange"))
+ # and also here:
+ print(create_object("banane"))
=====================================
docs/source/white_paper.rst
=====================================
@@ -13,7 +13,7 @@ The Python Standard Library
---------------------------
:Library: Python_
-:GitHub: `python/cpython <https://github.com/python/cpython.git>`_.
+:GitHub: `python/cpython <https://github.com/python/cpython>`_.
:Version: v3.8.dev
An example of function deprecation can be found in the :mod:`urllib` module (:file:`Lib/urllib/parse.py`):
@@ -122,7 +122,7 @@ The Flask Library
-----------------
:Library: Flask_
-:GitHub: `pallets/flask <https://github.com/pallets/flask.git>`_.
+:GitHub: `pallets/flask <https://github.com/pallets/flask>`_.
:Version: v1.1.dev
In the source code of Flask, we find only few deprecations: in the :mod:`~flask.app` (:file:`flask/app.py`)
@@ -196,7 +196,7 @@ The Django Library
------------------
:Library: Django
-:GitHub: `django/django <https://github.com/django/django.git>`_.
+:GitHub: `django/django <https://github.com/django/django>`_.
:Version: v3.0.dev
The `Django`_ Library defines several categories for deprecation in the module :mod:`django.utils.deprecation`:
@@ -283,7 +283,7 @@ The lxml Library
----------------
:Library: lxml_
-:GitHub: `lxml/lxml <https://github.com/lxml/lxml.git>`_.
+:GitHub: `lxml/lxml <https://github.com/lxml/lxml>`_.
:Version: v4.3.2.dev
The lxml_ Library is developed in Cython, not Python. But, it is a similar language.
=====================================
python-deprecated.spec
=====================================
@@ -2,11 +2,11 @@
%global pkgname deprecated
Name: python-%{pkgname}
-Version: 1.2.14
+Version: 1.2.15
Release: 1%{?dist}
Summary: Python decorator to deprecate old python classes, functions or methods
License: MIT
-URL: https://github.com/tantale/%{pkgname}
+URL: https://github.com/laurent-laporte-pro/%{pkgname}
Source0: %{pypi_source}
BuildArch: noarch
=====================================
setup.py
=====================================
@@ -130,67 +130,71 @@ Run it:
Links
`````
-* `Python package index (PyPi) <https://pypi.python.org/pypi/deprecated>`_
-* `GitHub website <https://github.com/tantale/deprecated>`_
+* `Python package index (PyPi) <https://pypi.org/project/Deprecated/>`_
+* `GitHub website <https://github.com/laurent-laporte-pro/deprecated>`_
* `Read The Docs <https://readthedocs.org/projects/deprecated>`_
* `EBook on Lulu.com <http://www.lulu.com/commerce/index.php?fBuyContent=21305117>`_
* `StackOverFlow Q&A <https://stackoverflow.com/a/40301488/1513933>`_
* `Development version
- <https://github.com/tantale/deprecated/zipball/master#egg=Deprecated-dev>`_
+ <https://github.com/laurent-laporte-pro/deprecated/zipball/master#egg=Deprecated-dev>`_
"""
+
from setuptools import setup
setup(
- name='Deprecated',
- version='1.2.14',
- url='https://github.com/tantale/deprecated',
+ name="Deprecated",
+ version="1.2.15",
+ url="https://github.com/laurent-laporte-pro/deprecated",
project_urls={
"Documentation": "https://deprecated.readthedocs.io/en/latest/",
- "Source": "https://github.com/tantale/deprecated",
- "Bug Tracker": "https://github.com/tantale/deprecated/issues",
+ "Source": "https://github.com/laurent-laporte-pro/deprecated",
+ "Bug Tracker": "https://github.com/laurent-laporte-pro/deprecated/issues",
},
- license='MIT',
- author='Laurent LAPORTE', # since v1.1.0
- author_email='tantale.solutions at gmail.com',
- description='Python @deprecated decorator to deprecate old python classes, functions or methods.',
+ license="MIT",
+ author="Laurent LAPORTE", # since v1.1.0
+ author_email="laurent.laporte.pro at gmail.com",
+ description="Python @deprecated decorator to deprecate old python classes, functions or methods.",
long_description=__doc__,
long_description_content_type="text/x-rst",
- keywords='deprecate,deprecated,deprecation,warning,warn,decorator',
- packages=['deprecated'],
- install_requires=['wrapt < 2, >= 1.10'],
+ keywords="deprecate,deprecated,deprecation,warning,warn,decorator",
+ packages=["deprecated"],
+ install_requires=["wrapt < 2, >= 1.10"],
zip_safe=False,
include_package_data=True,
- platforms='any',
+ platforms="any",
classifiers=[
- 'Development Status :: 5 - Production/Stable',
- 'Environment :: Web Environment',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: MIT License',
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 2',
- 'Programming Language :: Python :: 2.7',
- 'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.4',
- 'Programming Language :: Python :: 3.5',
- 'Programming Language :: Python :: 3.6',
- 'Programming Language :: Python :: 3.7',
- 'Programming Language :: Python :: 3.8',
- 'Programming Language :: Python :: 3.9',
- 'Programming Language :: Python :: 3.10',
- 'Programming Language :: Python :: 3.11',
- 'Programming Language :: Python :: 3.12',
- 'Topic :: Software Development :: Libraries :: Python Modules',
+ "Development Status :: 5 - Production/Stable",
+ "Environment :: Web Environment",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: MIT License",
+ "Operating System :: OS Independent",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 2",
+ "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.4",
+ "Programming Language :: Python :: 3.5",
+ "Programming Language :: Python :: 3.6",
+ "Programming Language :: Python :: 3.7",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
+ "Topic :: Software Development :: Libraries :: Python Modules",
],
extras_require={
- 'dev': [
- 'tox',
- 'PyTest',
- 'PyTest-Cov',
- 'bump2version < 1',
- 'sphinx < 2',
+ "dev": [
+ "tox",
+ "PyTest",
+ "PyTest-Cov",
+ "bump2version < 1",
+ "sphinx < 2",
+ # jinja2 3.0.3 was the last version to have contextfunction that sphinx 1.x needs
+ "jinja2~=3.0.3",
+ "setuptools; python_version>='3.12'",
]
},
- python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
+ python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
)
=====================================
tests/test_deprecated.py
=====================================
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
+import inspect
import sys
import warnings
@@ -11,6 +12,10 @@ class MyDeprecationWarning(DeprecationWarning):
pass
+class WrongStackLevelWarning(DeprecationWarning):
+ pass
+
+
_PARAMS = [
None,
((), {}),
@@ -19,6 +24,7 @@ _PARAMS = [
((), {'version': '1.2.3'}),
((), {'action': 'once'}),
((), {'category': MyDeprecationWarning}),
+ ((), {'extra_stacklevel': 1, 'category': WrongStackLevelWarning}),
]
@@ -136,7 +142,7 @@ def test_classic_deprecated_function__warns(classic_deprecated_function):
warn = warns[0]
assert issubclass(warn.category, DeprecationWarning)
assert "deprecated function (or staticmethod)" in str(warn.message)
- assert warn.filename == __file__, 'Incorrect warning stackLevel'
+ assert warn.filename == __file__ or warn.category is WrongStackLevelWarning, 'Incorrect warning stackLevel'
# noinspection PyShadowingNames
@@ -148,7 +154,7 @@ def test_classic_deprecated_class__warns(classic_deprecated_class):
warn = warns[0]
assert issubclass(warn.category, DeprecationWarning)
assert "deprecated class" in str(warn.message)
- assert warn.filename == __file__, 'Incorrect warning stackLevel'
+ assert warn.filename == __file__ or warn.category is WrongStackLevelWarning, 'Incorrect warning stackLevel'
# noinspection PyShadowingNames
@@ -161,7 +167,7 @@ def test_classic_deprecated_method__warns(classic_deprecated_method):
warn = warns[0]
assert issubclass(warn.category, DeprecationWarning)
assert "deprecated method" in str(warn.message)
- assert warn.filename == __file__, 'Incorrect warning stackLevel'
+ assert warn.filename == __file__ or warn.category is WrongStackLevelWarning, 'Incorrect warning stackLevel'
# noinspection PyShadowingNames
@@ -173,7 +179,7 @@ def test_classic_deprecated_static_method__warns(classic_deprecated_static_metho
warn = warns[0]
assert issubclass(warn.category, DeprecationWarning)
assert "deprecated function (or staticmethod)" in str(warn.message)
- assert warn.filename == __file__, 'Incorrect warning stackLevel'
+ assert warn.filename == __file__ or warn.category is WrongStackLevelWarning, 'Incorrect warning stackLevel'
# noinspection PyShadowingNames
@@ -185,11 +191,11 @@ def test_classic_deprecated_class_method__warns(classic_deprecated_class_method)
assert len(warns) == 1
warn = warns[0]
assert issubclass(warn.category, DeprecationWarning)
- if sys.version_info >= (3, 9):
+ if (3, 9) <= sys.version_info < (3, 13):
assert "deprecated class method" in str(warn.message)
else:
assert "deprecated function (or staticmethod)" in str(warn.message)
- assert warn.filename == __file__, 'Incorrect warning stackLevel'
+ assert warn.filename == __file__ or warn.category is WrongStackLevelWarning, 'Incorrect warning stackLevel'
def test_should_raise_type_error():
@@ -258,3 +264,61 @@ def test_respect_global_filter():
fun()
fun()
assert len(warns) == 1
+
+
+def test_default_stacklevel():
+ """
+ The objective of this unit test is to ensure that the triggered warning message,
+ when invoking the 'use_foo' function, correctly indicates the line where the
+ deprecated 'foo' function is called.
+ """
+
+ @deprecated.classic.deprecated
+ def foo():
+ pass
+
+ def use_foo():
+ foo()
+
+ with warnings.catch_warnings(record=True) as warns:
+ warnings.simplefilter("always")
+ use_foo()
+
+ # Check that the warning path matches the module path
+ warn = warns[0]
+ assert warn.filename == __file__
+
+ # Check that the line number points to the first line inside 'use_foo'
+ use_foo_lineno = inspect.getsourcelines(use_foo)[1]
+ assert warn.lineno == use_foo_lineno + 1
+
+
+def test_extra_stacklevel():
+ """
+ The unit test utilizes an 'extra_stacklevel' of 1 to ensure that the warning message
+ accurately identifies the caller of the deprecated function. It verifies that when
+ the 'use_foo' function is called, the warning message correctly indicates the line
+ where the call to 'use_foo' is made.
+ """
+
+ @deprecated.classic.deprecated(extra_stacklevel=1)
+ def foo():
+ pass
+
+ def use_foo():
+ foo()
+
+ def demo():
+ use_foo()
+
+ with warnings.catch_warnings(record=True) as warns:
+ warnings.simplefilter("always")
+ demo()
+
+ # Check that the warning path matches the module path
+ warn = warns[0]
+ assert warn.filename == __file__
+
+ # Check that the line number points to the first line inside 'demo'
+ demo_lineno = inspect.getsourcelines(demo)[1]
+ assert warn.lineno == demo_lineno + 1
=====================================
tests/test_sphinx.py
=====================================
@@ -301,7 +301,7 @@ def test_sphinx_deprecated_class_method__warns(sphinx_deprecated_class_method):
assert len(warns) == 1
warn = warns[0]
assert issubclass(warn.category, DeprecationWarning)
- if sys.version_info >= (3, 9):
+ if (3, 9) <= sys.version_info < (3, 13):
assert "deprecated class method" in str(warn.message)
else:
assert "deprecated function (or staticmethod)" in str(warn.message)
=====================================
tests/test_sphinx_class.py
=====================================
@@ -88,7 +88,7 @@ def test_subclass_deprecation_using_deprecated_decorator():
sys.version_info < (3, 3), reason="Classes should have mutable docstrings -- resolved in python 3.3"
)
def test_isinstance_versionadded():
- # https://github.com/tantale/deprecated/issues/48
+ # https://github.com/laurent-laporte-pro/deprecated/issues/48
@deprecated.sphinx.versionadded(version="X.Y", reason="some reason")
class VersionAddedCls:
pass
=====================================
tox.ini
=====================================
@@ -26,6 +26,7 @@ deps =
wrapt1.13: wrapt ~= 1.13.0
wrapt1.14: wrapt ~= 1.14.0
coverage
+ setuptools; python_version>="3.12"
[testenv:docs]
basepython = python
View it on GitLab: https://salsa.debian.org/debian-gis-team/python-deprecated/-/compare/fb8ba06b91e1f5ffb9059eb48bb2dfa57700f46b...7b4fa1e394368aa968a1f67efc74841be4fd63ec
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/python-deprecated/-/compare/fb8ba06b91e1f5ffb9059eb48bb2dfa57700f46b...7b4fa1e394368aa968a1f67efc74841be4fd63ec
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/20241116/62da1984/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list