extend warnings.warn with callee parameter
When you have some library, with some deprecated function `X`, you can use the `stacklevel=2` parameter
on `warnings.warn` to show the file-name and line-number of the routine calling `X`
But if you have some framework that calls the user provided code, either through plug-ins or
by explicit registering, the `stacklevel` doesn't help you to complain about return values
that are deprecated.
This library extends `warnings.warn` with a `callee` parameter. If this is provided `stacklevel` should
not be provided and the value for `callee` should be a method or function for
which the warning is raised.
The warning will usually be a `PendingDeprecationWarning`, a `DeprecationWarning` or a subclass of either.
As an example, if you have two files `p0.py` and `p2.py` both with content::
class PlugIn:
def status(self):
return {'result': 'ok'}
And a file `p1.py`:
class PlugIn:
def status(self):
return ['ok'] # this plug-in has been updated
And these files are in a subfolder `plug_ins` where your framework can find them. Then running::
import sys
from pathlib import Path
from importlib import import_module
import ruamel.std.warnings
import warnings
class DictReturnPendingDeprecationWarning(PendingDeprecationWarning):
pass
class Driver:
def __init__(self):
self.plug_ins = []
def load_plug_ins(self):
sys.path.append('plug_ins')
for file_name in Path('plug_ins').glob('p*.py'):
mod = import_module(file_name.stem)
self.plug_ins.append(mod.PlugIn())
def check_status(self):
for p in self.plug_ins:
retval = p.status()
if isinstance(retval, dict):
# assume dict
warnings.warn(
'callable should return list, not dict',
DictReturnPendingDeprecationWarning,
callee=p.status,
)
else:
pass # assume list
warnings.simplefilter('once', PendingDeprecationWarning)
def doit():
driver = Driver()
driver.load_plug_ins()
for idx in range(2):
driver.check_status()
warnings.warn('almost done', PendingDeprecationWarning)
doit()
will result in::
/tmp/plug_ins/p0.py:2: DictReturnPendingDeprecationWarning: callable should return list, not dict
def status(self):
/tmp/plug_ins/p2.py:2: DictReturnPendingDeprecationWarning: callable should return list, not dict
def status(self):
/tmp/tmp_00.py:40: PendingDeprecationWarning: almost done
warnings.warn('almost done', PendingDeprecationWarning)
Raw data
{
"_id": null,
"home_page": "https://sourceforge.net/p/ruamel-std-warning/code/ci/default/tree",
"name": "ruamel.std.warning",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3",
"maintainer_email": "",
"keywords": "pypi statistics",
"author": "Anthon van der Neut",
"author_email": "a.van.der.neut@ruamel.eu",
"download_url": "https://files.pythonhosted.org/packages/01/46/16f7c1eec73296b7122e072fda9cb65da9127ab40970eccad2c45df1a67c/ruamel.std.warning-0.2.1.tar.gz",
"platform": null,
"description": "\nextend warnings.warn with callee parameter\n\nWhen you have some library, with some deprecated function `X`, you can use the `stacklevel=2` parameter \non `warnings.warn` to show the file-name and line-number of the routine calling `X`\n\nBut if you have some framework that calls the user provided code, either through plug-ins or\nby explicit registering, the `stacklevel` doesn't help you to complain about return values\nthat are deprecated.\n\nThis library extends `warnings.warn` with a `callee` parameter. If this is provided `stacklevel` should\nnot be provided and the value for `callee` should be a method or function for\nwhich the warning is raised.\n\nThe warning will usually be a `PendingDeprecationWarning`, a `DeprecationWarning` or a subclass of either.\n\nAs an example, if you have two files `p0.py` and `p2.py` both with content::\n\n class PlugIn:\n def status(self):\n return {'result': 'ok'}\n\nAnd a file `p1.py`:\n\n class PlugIn:\n def status(self):\n return ['ok'] # this plug-in has been updated\n\nAnd these files are in a subfolder `plug_ins` where your framework can find them. Then running::\n\n\n import sys\n from pathlib import Path\n from importlib import import_module\n import ruamel.std.warnings\n import warnings\n\n class DictReturnPendingDeprecationWarning(PendingDeprecationWarning):\n pass\n\n class Driver:\n def __init__(self):\n self.plug_ins = []\n\n def load_plug_ins(self):\n sys.path.append('plug_ins')\n for file_name in Path('plug_ins').glob('p*.py'):\n mod = import_module(file_name.stem) \n self.plug_ins.append(mod.PlugIn())\n\n def check_status(self):\n for p in self.plug_ins:\n retval = p.status()\n if isinstance(retval, dict):\n # assume dict\n warnings.warn(\n 'callable should return list, not dict',\n DictReturnPendingDeprecationWarning,\n callee=p.status,\n )\n else:\n pass # assume list\n\n warnings.simplefilter('once', PendingDeprecationWarning)\n\n def doit():\n driver = Driver()\n driver.load_plug_ins()\n for idx in range(2):\n driver.check_status()\n warnings.warn('almost done', PendingDeprecationWarning)\n\n doit()\n\nwill result in::\n\n /tmp/plug_ins/p0.py:2: DictReturnPendingDeprecationWarning: callable should return list, not dict\n def status(self):\n /tmp/plug_ins/p2.py:2: DictReturnPendingDeprecationWarning: callable should return list, not dict\n def status(self):\n /tmp/tmp_00.py:40: PendingDeprecationWarning: almost done\n warnings.warn('almost done', PendingDeprecationWarning)\n",
"bugtrack_url": null,
"license": "Copyright Ruamel bvba 2007-2023",
"summary": "extend warnings.warn with callee parameter",
"version": "0.2.1",
"project_urls": {
"Homepage": "https://sourceforge.net/p/ruamel-std-warning/code/ci/default/tree"
},
"split_keywords": [
"pypi",
"statistics"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "f79c8ebe9198180136774c42a348180864c48dba158000bf4324152f6830696e",
"md5": "20348283085c5c197dc0cbba7e6c5290",
"sha256": "3fd7a811630f5b88d3fdb91c2d06457fb443ee7b9bb0fa02f666e397dda1e609"
},
"downloads": -1,
"filename": "ruamel.std.warning-0.2.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "20348283085c5c197dc0cbba7e6c5290",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3",
"size": 3628,
"upload_time": "2023-07-26T12:09:37",
"upload_time_iso_8601": "2023-07-26T12:09:37.629467Z",
"url": "https://files.pythonhosted.org/packages/f7/9c/8ebe9198180136774c42a348180864c48dba158000bf4324152f6830696e/ruamel.std.warning-0.2.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "014616f7c1eec73296b7122e072fda9cb65da9127ab40970eccad2c45df1a67c",
"md5": "fcb68f1daa12c5fbd54472556b1331ec",
"sha256": "2a86dcf2616b4e411526fa4f8ac20d51c6cef2b8ae7dcee9736493a8202b85c9"
},
"downloads": -1,
"filename": "ruamel.std.warning-0.2.1.tar.gz",
"has_sig": false,
"md5_digest": "fcb68f1daa12c5fbd54472556b1331ec",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3",
"size": 12405,
"upload_time": "2023-07-26T12:09:35",
"upload_time_iso_8601": "2023-07-26T12:09:35.973729Z",
"url": "https://files.pythonhosted.org/packages/01/46/16f7c1eec73296b7122e072fda9cb65da9127ab40970eccad2c45df1a67c/ruamel.std.warning-0.2.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-07-26 12:09:35",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "ruamel.std.warning"
}