mdis


Namemdis JSON
Version 0.5.1 PyPI version JSON
download
home_page
SummaryPython dispatching library
upload_time2023-06-21 18:48:13
maintainer
docs_urlNone
author
requires_python>=3.0
license
keywords dispatch dispather map iterator iterable visitor walker
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # About this project

The mdis module allows to quickly extend the classes with the required functionality without modifications inside these classes.
This is done via double dispatch pattern: the dispatcher describes the required action based on the the argument type.
Use cases mainly include visitors and iterators, but are not limited to them.

# Dispatchers

The key concept of this module is dispatcher. A dispatcher object is a callable object; the exact call logic depends on the type of the argument.
The main class, `mdis.dispatcher.Dispatcher`, can register per-type hooks, which modify the call logic depending on the argument.
The hook is registered on a dispatcher class level as a method; attempts to call a dispatcher determine the relevant hooks based on argument type.

# Walkers

Sometimes objects of different types need to be traversed, but either lack `__iter__` method, or its semantics differs from what the users want.
For example, let's consider a nested collection, consisting of tuples, dicts and other types.
`dict.__iter__` method yields just keys, and the values have to be got via `__getitem__` calls.
Also, in order to support nested collections, users will have to write some recursive code with `isinstance` checks.
With `mdis.Walker`, users can just install the handlers for the types of interest, and change the iteration logic.
A walker is just a particular example of dispatcher, where the call yields some objects in a class-dependent manner.
The default `mdis.Walker` already incorporates the logic to walk over some builtin Python objects.
The example below shows how to override the way the dicts are traversed so that keys and values are swapped.

    import mdis.dispatcher
    import mdis.walker

    class CustomWalker(mdis.walker.Walker):
        @mdis.dispatcher.hook(dict)
        def dispatch_dict(self, instance):
            for (key, value) in instance.items():
                yield (value, key)
                yield from self((value, key))

    collection = {"a": 1, "b": 2}
    walker = CustomWalker()
    for item in walker(collection):
        print(item)

The following output is expected:

    (1, 'a')
    1
    a
    (2, 'b')
    2
    b

# Visitors

In `mdis`, a visitor is just another particular example of dispatcher.
Whenever the visitor is called, the call is dispatched based on type, and some per-class action is performed.
The primary scenario is to combine the visitor calls with context managers.
The example below shows how to execute some arbitrary code upon visiting an object.

    import contextlib

    import mdis.dispatcher
    import mdis.visitor

    class CustomVisitor(mdis.visitor.ContextVisitor):
        @mdis.dispatcher.hook(int)
        @contextlib.contextmanager
        def dispatch_int(self, instance):
            print("entering int")
            yield (instance + 42)
            print("leaving int")

        @mdis.dispatcher.hook(str)
        @contextlib.contextmanager
        def dispatch_str(self, instance):
            print("entering str")
            yield f"!!!{instance}!!!"
            print("leaving str")

        @mdis.dispatcher.hook(object)
        @contextlib.contextmanager
        def dispatch_object(self, instance):
            print("entering object")
            yield instance
            print("leaving object")

    visitor = CustomVisitor()
    for item in (42, "cocojamboo", 1.5):
        with visitor(item) as result:
            print(result)

The following output is expected:

    entering int
    84
    leaving int
    entering str
    !!!cocojamboo!!!
    leaving str
    entering object
    1.5
    leaving object

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "mdis",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.0",
    "maintainer_email": "",
    "keywords": "dispatch,dispather,map,iterator,iterable,visitor,walker",
    "author": "",
    "author_email": "Dmitry Selyutin <ghostmansd@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/1d/96/caddd7f619732b1a1c4ee8b2ecf9ab00c35730f00c14c96e448cf48a3a35/mdis-0.5.1.tar.gz",
    "platform": null,
    "description": "# About this project\n\nThe mdis module allows to quickly extend the classes with the required functionality without modifications inside these classes.\nThis is done via double dispatch pattern: the dispatcher describes the required action based on the the argument type.\nUse cases mainly include visitors and iterators, but are not limited to them.\n\n# Dispatchers\n\nThe key concept of this module is dispatcher. A dispatcher object is a callable object; the exact call logic depends on the type of the argument.\nThe main class, `mdis.dispatcher.Dispatcher`, can register per-type hooks, which modify the call logic depending on the argument.\nThe hook is registered on a dispatcher class level as a method; attempts to call a dispatcher determine the relevant hooks based on argument type.\n\n# Walkers\n\nSometimes objects of different types need to be traversed, but either lack `__iter__` method, or its semantics differs from what the users want.\nFor example, let's consider a nested collection, consisting of tuples, dicts and other types.\n`dict.__iter__` method yields just keys, and the values have to be got via `__getitem__` calls.\nAlso, in order to support nested collections, users will have to write some recursive code with `isinstance` checks.\nWith `mdis.Walker`, users can just install the handlers for the types of interest, and change the iteration logic.\nA walker is just a particular example of dispatcher, where the call yields some objects in a class-dependent manner.\nThe default `mdis.Walker` already incorporates the logic to walk over some builtin Python objects.\nThe example below shows how to override the way the dicts are traversed so that keys and values are swapped.\n\n    import mdis.dispatcher\n    import mdis.walker\n\n    class CustomWalker(mdis.walker.Walker):\n        @mdis.dispatcher.hook(dict)\n        def dispatch_dict(self, instance):\n            for (key, value) in instance.items():\n                yield (value, key)\n                yield from self((value, key))\n\n    collection = {\"a\": 1, \"b\": 2}\n    walker = CustomWalker()\n    for item in walker(collection):\n        print(item)\n\nThe following output is expected:\n\n    (1, 'a')\n    1\n    a\n    (2, 'b')\n    2\n    b\n\n# Visitors\n\nIn `mdis`, a visitor is just another particular example of dispatcher.\nWhenever the visitor is called, the call is dispatched based on type, and some per-class action is performed.\nThe primary scenario is to combine the visitor calls with context managers.\nThe example below shows how to execute some arbitrary code upon visiting an object.\n\n    import contextlib\n\n    import mdis.dispatcher\n    import mdis.visitor\n\n    class CustomVisitor(mdis.visitor.ContextVisitor):\n        @mdis.dispatcher.hook(int)\n        @contextlib.contextmanager\n        def dispatch_int(self, instance):\n            print(\"entering int\")\n            yield (instance + 42)\n            print(\"leaving int\")\n\n        @mdis.dispatcher.hook(str)\n        @contextlib.contextmanager\n        def dispatch_str(self, instance):\n            print(\"entering str\")\n            yield f\"!!!{instance}!!!\"\n            print(\"leaving str\")\n\n        @mdis.dispatcher.hook(object)\n        @contextlib.contextmanager\n        def dispatch_object(self, instance):\n            print(\"entering object\")\n            yield instance\n            print(\"leaving object\")\n\n    visitor = CustomVisitor()\n    for item in (42, \"cocojamboo\", 1.5):\n        with visitor(item) as result:\n            print(result)\n\nThe following output is expected:\n\n    entering int\n    84\n    leaving int\n    entering str\n    !!!cocojamboo!!!\n    leaving str\n    entering object\n    1.5\n    leaving object\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "Python dispatching library",
    "version": "0.5.1",
    "project_urls": {
        "Bug Tracker": "https://bugs.libre-soc.org/",
        "Homepage": "https://git.libre-soc.org/?p=mdis.git"
    },
    "split_keywords": [
        "dispatch",
        "dispather",
        "map",
        "iterator",
        "iterable",
        "visitor",
        "walker"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "be904e3fa77969e929ec554e4a78737679b796cda16d8f432b7d2a34a692eb68",
                "md5": "88aa270b5e3030605d58c4b9b8aba166",
                "sha256": "b92472b11afa70cea7917f487296d1ba771bbec40d49fc121a2d1b85350bc73f"
            },
            "downloads": -1,
            "filename": "mdis-0.5.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "88aa270b5e3030605d58c4b9b8aba166",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.0",
            "size": 5933,
            "upload_time": "2023-06-21T18:48:12",
            "upload_time_iso_8601": "2023-06-21T18:48:12.382313Z",
            "url": "https://files.pythonhosted.org/packages/be/90/4e3fa77969e929ec554e4a78737679b796cda16d8f432b7d2a34a692eb68/mdis-0.5.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "1d96caddd7f619732b1a1c4ee8b2ecf9ab00c35730f00c14c96e448cf48a3a35",
                "md5": "1a20c2023dd664441214c8a6ac73a7dc",
                "sha256": "82f5ed3fc34ee573c302cd1731b1a49c6efd16c70dffb971aa6175920de78718"
            },
            "downloads": -1,
            "filename": "mdis-0.5.1.tar.gz",
            "has_sig": false,
            "md5_digest": "1a20c2023dd664441214c8a6ac73a7dc",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.0",
            "size": 5023,
            "upload_time": "2023-06-21T18:48:13",
            "upload_time_iso_8601": "2023-06-21T18:48:13.725466Z",
            "url": "https://files.pythonhosted.org/packages/1d/96/caddd7f619732b1a1c4ee8b2ecf9ab00c35730f00c14c96e448cf48a3a35/mdis-0.5.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-06-21 18:48:13",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "mdis"
}
        
Elapsed time: 0.08912s