# Overview
`preoccupied.proxytype` is a [Python] package providing a [MyPy]
plugin and a class decorator for triggering that plugin. The decorator
can be used to indicate that a decorated class should be considered
during static analysis to posess all of the methods from another
class.
[python]: https://python.org
[MyPy]: https://mypy-lang.org
This pattern is distinct from inheritance, in that it will also apply
a transformation to the return type of the copied methods. It is valid
for this transformed return type to be incompatible with the original
template class's method signature.
This is useful in situations where a dynamic class wraps or proxies
its calls to another instance, optionally decorating them in the
process.
The class decorator has no behavior at runtime -- it does not
implement the proxying. It is only there to provide a way to declare
such behavior during static analysis.
## Installation
Install from the latest PyPI release
```bash
pip install --user preoccupied.proxytype
```
Install from a git checkout
```bash
make install
```
## Enable plugin
At runtime the proxytype class decorator does not introduce a MyPy
dependency. However in order for it to operate during MyPy's static
analysis checks the plugin must be enabled. For example in `setup.cfg`
```ini filename=setup.cfg
[mypy]
plugins =
preoccupied.proxytype
```
## Usage of proxytype
At runtime the proxytype class decorator has no impact. During static
analysis via MyPy the proxytype class decorator can be used to
virtually annotate that class with the methods from the originating
type. Methods brought across to the decorated type will have their
self argument type updated, and can optionally have their return type
modified to be a wrapped generic around the original return type.
For example:
```python
from preoccupied.proxytype import proxytype
class ClientSession:
def doSomething(self, how_many: int, etc: Any) -> List[int]:
...
def doAnother(self, wut: Any, **kwds: Any) -> bool:
...
def getName(self) -> str:
...
RT = TypeVar("RT")
class DelayResult(Generic[RT]):
resultValue: RT
@proxytype(ClientSession, DelayResult)
class DelayClientSession:
def getName(self) -> str:
...
```
This will cause static analysys via MyPy of the `DelayClientSession`
to appear as if it had been declared as:
```python
class DelayClientSession:
def doSomething(self, how_many: int, etc: Any) -> DelayResult[List[int]]:
...
def doAnother(self, wut: Any, **kwds: Any) -> DelayResult[bool]:
...
def getName(self) -> str:
...
```
## Contact
author: Christopher O'Brien <obriencj@preoccupied.net>
original git repository: <https://github.com/obriencj/python-proxytype>
pypi project: <https://pypi.org/project/preoccupied.proxytype>
## License
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 3 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see
<http://www.gnu.org/licenses/>.
Raw data
{
"_id": null,
"home_page": "https://github.com/obriencj/python-proxytype",
"name": "preoccupied.proxytype",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": null,
"author": "Christopher O'Brien",
"author_email": "obriencj@preoccupied.net",
"download_url": "https://files.pythonhosted.org/packages/2f/71/4cedc7bbe803d42a774f189f1ea8ca8f42b98bae665e49bed855fcd2ddf6/preoccupied_proxytype-0.4.0.tar.gz",
"platform": "any",
"description": "# Overview\n\n`preoccupied.proxytype` is a [Python] package providing a [MyPy]\nplugin and a class decorator for triggering that plugin. The decorator\ncan be used to indicate that a decorated class should be considered\nduring static analysis to posess all of the methods from another\nclass.\n\n[python]: https://python.org\n\n[MyPy]: https://mypy-lang.org\n\nThis pattern is distinct from inheritance, in that it will also apply\na transformation to the return type of the copied methods. It is valid\nfor this transformed return type to be incompatible with the original\ntemplate class's method signature.\n\nThis is useful in situations where a dynamic class wraps or proxies\nits calls to another instance, optionally decorating them in the\nprocess.\n\nThe class decorator has no behavior at runtime -- it does not\nimplement the proxying. It is only there to provide a way to declare\nsuch behavior during static analysis.\n\n\n## Installation\n\nInstall from the latest PyPI release\n\n```bash\npip install --user preoccupied.proxytype\n```\n\nInstall from a git checkout\n\n```bash\nmake install\n```\n\n\n## Enable plugin\n\nAt runtime the proxytype class decorator does not introduce a MyPy\ndependency. However in order for it to operate during MyPy's static\nanalysis checks the plugin must be enabled. For example in `setup.cfg`\n\n```ini filename=setup.cfg\n[mypy]\nplugins =\n preoccupied.proxytype\n```\n\n\n## Usage of proxytype\n\nAt runtime the proxytype class decorator has no impact. During static\nanalysis via MyPy the proxytype class decorator can be used to\nvirtually annotate that class with the methods from the originating\ntype. Methods brought across to the decorated type will have their\nself argument type updated, and can optionally have their return type\nmodified to be a wrapped generic around the original return type.\n\nFor example:\n\n```python\nfrom preoccupied.proxytype import proxytype\n\n\nclass ClientSession:\n def doSomething(self, how_many: int, etc: Any) -> List[int]:\n ...\n\n def doAnother(self, wut: Any, **kwds: Any) -> bool:\n ...\n\n def getName(self) -> str:\n ...\n\n\nRT = TypeVar(\"RT\")\n\nclass DelayResult(Generic[RT]):\n resultValue: RT\n\n\n@proxytype(ClientSession, DelayResult)\nclass DelayClientSession:\n def getName(self) -> str:\n ...\n```\n\nThis will cause static analysys via MyPy of the `DelayClientSession`\nto appear as if it had been declared as:\n\n```python\nclass DelayClientSession:\n def doSomething(self, how_many: int, etc: Any) -> DelayResult[List[int]]:\n ...\n\n def doAnother(self, wut: Any, **kwds: Any) -> DelayResult[bool]:\n ...\n\n def getName(self) -> str:\n ...\n```\n\n\n## Contact\n\nauthor: Christopher O'Brien <obriencj@preoccupied.net>\n\noriginal git repository: <https://github.com/obriencj/python-proxytype>\n\npypi project: <https://pypi.org/project/preoccupied.proxytype>\n\n\n## License\n\nThis library is free software; you can redistribute it and/or modify\nit under the terms of the GNU Lesser General Public License as\npublished by the Free Software Foundation; either version 3 of the\nLicense, or (at your option) any later version.\n\nThis library is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\nLesser General Public License for more details.\n\nYou should have received a copy of the GNU Lesser General Public\nLicense along with this library; if not, see\n<http://www.gnu.org/licenses/>.\n",
"bugtrack_url": null,
"license": "GNU General Public License v3 (GPLv3)",
"summary": "static typing support for dynamic proxy classes",
"version": "0.4.0",
"project_urls": {
"Homepage": "https://github.com/obriencj/python-proxytype",
"Issues": "https://github.com/obriencj/python-proxytype/issues",
"Source": "https://github.com/obriencj/python-proxytype"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "ccced2d49b40361fb14b427efcc31e6662460f1332df6fc0c3329f016d2a0a9e",
"md5": "42590983858fc65fc96f08d4e11cd619",
"sha256": "43f9bce83a1e28575cbc63b6314f9da29117a88d9aafd672cdbb882e84a315e5"
},
"downloads": -1,
"filename": "preoccupied.proxytype-0.4.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "42590983858fc65fc96f08d4e11cd619",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 17983,
"upload_time": "2024-07-06T18:06:05",
"upload_time_iso_8601": "2024-07-06T18:06:05.497968Z",
"url": "https://files.pythonhosted.org/packages/cc/ce/d2d49b40361fb14b427efcc31e6662460f1332df6fc0c3329f016d2a0a9e/preoccupied.proxytype-0.4.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "2f714cedc7bbe803d42a774f189f1ea8ca8f42b98bae665e49bed855fcd2ddf6",
"md5": "968a7aa904182806fcc3282542e3de4d",
"sha256": "bfda4a9e7584ab371dcd43ecf51a3825e62a4a950ea06c47818f9585c4b6c748"
},
"downloads": -1,
"filename": "preoccupied_proxytype-0.4.0.tar.gz",
"has_sig": false,
"md5_digest": "968a7aa904182806fcc3282542e3de4d",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 16950,
"upload_time": "2024-07-06T18:06:07",
"upload_time_iso_8601": "2024-07-06T18:06:07.063943Z",
"url": "https://files.pythonhosted.org/packages/2f/71/4cedc7bbe803d42a774f189f1ea8ca8f42b98bae665e49bed855fcd2ddf6/preoccupied_proxytype-0.4.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-07-06 18:06:07",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "obriencj",
"github_project": "python-proxytype",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "preoccupied.proxytype"
}