# inspect313
[![test](https://github.com/wemake-services/inspect313/actions/workflows/test.yml/badge.svg?branch=master&event=push)](https://github.com/wemake-services/inspect313/actions/workflows/test.yml)
[![Python Version](https://img.shields.io/pypi/pyversions/inspect313.svg)](https://pypi.org/project/inspect313/)
Backport of `inspect` module from Python3.13, supports Python 3.8+
## Features
- Fully typed with annotations and checked with mypy, [PEP561 compatible](https://www.python.org/dev/peps/pep-0561/)
- Has backported `skip_bound_arg` argument to `signature` and `Signature.from_callable`
## Installation
```bash
pip install inspect313
```
## Examples
### Replace `inspect.getfullargspec` with `inspect.signature`
`getfullargspec` is an old way of getting the function signature.
It is [deprecated](https://github.com/python/cpython/issues/108901) since Python 3.13,
and new `skip_bound_arg: bool = True` argument was introduced in the same version.
However, this change was not backported, so users of older Python versions
need this package to have the same functionality.
Here's how `getfullargspec` is different from regular `signature` call:
- the `self` / `cls` parameter is always reported, even for bound methods
```python
>>> import inspect
>>> class A:
... def method(self, arg: int) -> None: ...
>>> inspect.getfullargspec(A().method)
FullArgSpec(args=['self', 'arg'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={'return': None, 'arg': <class 'int'>})
>>> # signature() produces a different result:
>>> inspect.signature(A().method)
<Signature (arg: int) -> None>
```
- wrapper chains defined by `__wrapped__` *not* unwrapped automatically
```python
>>> import functools
>>> def some_decorator(f):
... @functools.wraps(f)
... def wrapper(*args, **kwargs):
... return f(*args, **kwargs)
... return wrapper
>>> @some_decorator
... def func(a: int, /, b: str) -> None: ...
>>> inspect.getfullargspec(func)
FullArgSpec(args=[], varargs='args', varkw='kwargs', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={'return': None})
>>> # signature() produces a different result:
>>> inspect.signature(func)
<Signature (a: int, /, b: str) -> None>
```
Here's how you can migrate, these results will be in line with `getfullargspec`:
```python
>>> import inspect313
>>> inspect313.signature(
... A().method,
... skip_bound_arg=False,
... follow_wrapped=False,
... )
<Signature (self, arg: int) -> None>
>>> inspect313.signature(
... func,
... skip_bound_arg=False,
... follow_wrapped=False,
... )
<Signature (*args, **kwargs) -> None>
```
However, consider migrating to just using `inspect.signature`,
since it produces more correct results in a general case.
### Replace `inspect.getargvalues` with `inspect.Signature.from_frame`
`getargvalues` was used to create signature-like objects from frame objects.
But, it didn't really support all features of modern functions.
This is why Python 3.13 introduced `inspect.Signature.from_frame`
public constructor and `getargvalues` and `formatargvalues` were deprecated.
Here's how it worked before:
```python
>>> import inspect
>>> def func(a: int = 0, /, b: int = 1, *, c: int = 2):
... return inspect.currentframe()
>>> frame = func()
>>> # notice that pos-only and kw-only args are not supported properly:
>>> inspect.formatargvalues(*inspect.getargvalues(frame))
'(a=0, b=1, c=2)'
```
Here's how to replace it with modern API:
```python
>>> from inspect313 import Signature
>>> str(Signature.from_frame(frame))
'(a=0, /, b=1, *, c=2)'
```
## License
[MIT](https://github.com/wemake-services/inspect313/blob/master/LICENSE)
Raw data
{
"_id": null,
"home_page": "https://github.com/wemake-services/inspect313",
"name": "inspect313",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8,<4.0",
"maintainer_email": "",
"keywords": "inspect,python,signature,backport",
"author": "sobolevn",
"author_email": "mail@sobolevn.me",
"download_url": "https://files.pythonhosted.org/packages/e7/2a/c0fc7c51490ecc067ab230f996f7998f5ab13276f00bec273ae87c193e67/inspect313-0.1.0.tar.gz",
"platform": null,
"description": "# inspect313\n\n[![test](https://github.com/wemake-services/inspect313/actions/workflows/test.yml/badge.svg?branch=master&event=push)](https://github.com/wemake-services/inspect313/actions/workflows/test.yml)\n[![Python Version](https://img.shields.io/pypi/pyversions/inspect313.svg)](https://pypi.org/project/inspect313/)\n\nBackport of `inspect` module from Python3.13, supports Python 3.8+\n\n## Features\n\n- Fully typed with annotations and checked with mypy, [PEP561 compatible](https://www.python.org/dev/peps/pep-0561/)\n- Has backported `skip_bound_arg` argument to `signature` and `Signature.from_callable`\n\n## Installation\n\n```bash\npip install inspect313\n```\n\n## Examples\n\n### Replace `inspect.getfullargspec` with `inspect.signature`\n\n`getfullargspec` is an old way of getting the function signature.\nIt is [deprecated](https://github.com/python/cpython/issues/108901) since Python 3.13,\nand new `skip_bound_arg: bool = True` argument was introduced in the same version.\n\nHowever, this change was not backported, so users of older Python versions\nneed this package to have the same functionality.\n\nHere's how `getfullargspec` is different from regular `signature` call:\n\n- the `self` / `cls` parameter is always reported, even for bound methods\n\n```python\n>>> import inspect\n\n>>> class A:\n... def method(self, arg: int) -> None: ...\n\n>>> inspect.getfullargspec(A().method)\nFullArgSpec(args=['self', 'arg'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={'return': None, 'arg': <class 'int'>})\n\n>>> # signature() produces a different result:\n>>> inspect.signature(A().method)\n<Signature (arg: int) -> None>\n\n```\n\n- wrapper chains defined by `__wrapped__` *not* unwrapped automatically\n\n```python\n>>> import functools\n\n>>> def some_decorator(f):\n... @functools.wraps(f)\n... def wrapper(*args, **kwargs):\n... return f(*args, **kwargs)\n... return wrapper\n\n>>> @some_decorator\n... def func(a: int, /, b: str) -> None: ...\n\n>>> inspect.getfullargspec(func)\nFullArgSpec(args=[], varargs='args', varkw='kwargs', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={'return': None})\n\n>>> # signature() produces a different result:\n>>> inspect.signature(func)\n<Signature (a: int, /, b: str) -> None>\n\n```\n\nHere's how you can migrate, these results will be in line with `getfullargspec`:\n\n```python\n>>> import inspect313\n\n>>> inspect313.signature(\n... A().method,\n... skip_bound_arg=False,\n... follow_wrapped=False,\n... )\n<Signature (self, arg: int) -> None>\n\n>>> inspect313.signature(\n... func,\n... skip_bound_arg=False,\n... follow_wrapped=False,\n... )\n<Signature (*args, **kwargs) -> None>\n\n```\n\nHowever, consider migrating to just using `inspect.signature`,\nsince it produces more correct results in a general case.\n\n### Replace `inspect.getargvalues` with `inspect.Signature.from_frame`\n\n`getargvalues` was used to create signature-like objects from frame objects.\nBut, it didn't really support all features of modern functions.\n\nThis is why Python 3.13 introduced `inspect.Signature.from_frame`\npublic constructor and `getargvalues` and `formatargvalues` were deprecated.\n\nHere's how it worked before:\n\n```python\n>>> import inspect\n\n>>> def func(a: int = 0, /, b: int = 1, *, c: int = 2):\n... return inspect.currentframe()\n\n>>> frame = func()\n>>> # notice that pos-only and kw-only args are not supported properly:\n>>> inspect.formatargvalues(*inspect.getargvalues(frame))\n'(a=0, b=1, c=2)'\n\n```\n\nHere's how to replace it with modern API:\n\n```python\n>>> from inspect313 import Signature\n\n>>> str(Signature.from_frame(frame))\n'(a=0, /, b=1, *, c=2)'\n\n```\n\n## License\n\n[MIT](https://github.com/wemake-services/inspect313/blob/master/LICENSE)\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Backport of `inspect` module from Python3.13",
"version": "0.1.0",
"project_urls": {
"Homepage": "https://github.com/wemake-services/inspect313",
"Repository": "https://github.com/wemake-services/inspect313"
},
"split_keywords": [
"inspect",
"python",
"signature",
"backport"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "e03b6f4ccbcf83977713f866b5fcd8ac23c58b25d93629ba78e715b255648694",
"md5": "90e900074665458906b1cb0f3224e2ad",
"sha256": "ad21191a2a715a0d5c231c66848829d3e00ae754c7cc3f6416e258eb2bf85207"
},
"downloads": -1,
"filename": "inspect313-0.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "90e900074665458906b1cb0f3224e2ad",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8,<4.0",
"size": 4624,
"upload_time": "2024-03-09T07:52:29",
"upload_time_iso_8601": "2024-03-09T07:52:29.831620Z",
"url": "https://files.pythonhosted.org/packages/e0/3b/6f4ccbcf83977713f866b5fcd8ac23c58b25d93629ba78e715b255648694/inspect313-0.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "e72ac0fc7c51490ecc067ab230f996f7998f5ab13276f00bec273ae87c193e67",
"md5": "92f3941f0a5516ff8b5a5c28c2f35a7f",
"sha256": "9dcedd40bc006043da1ff3fa720d3c25c0dc2e28c5f543e539df3a1b5064c1e6"
},
"downloads": -1,
"filename": "inspect313-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "92f3941f0a5516ff8b5a5c28c2f35a7f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8,<4.0",
"size": 4355,
"upload_time": "2024-03-09T07:52:33",
"upload_time_iso_8601": "2024-03-09T07:52:33.189917Z",
"url": "https://files.pythonhosted.org/packages/e7/2a/c0fc7c51490ecc067ab230f996f7998f5ab13276f00bec273ae87c193e67/inspect313-0.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-03-09 07:52:33",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "wemake-services",
"github_project": "inspect313",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "inspect313"
}