troopy


Nametroopy JSON
Version 0.1.0 PyPI version JSON
download
home_pagehttps://github.com/kodemore/troopy
SummaryCommand Bus/Message Bus implementation for python
upload_time2020-07-05 19:29:40
maintainer
docs_urlNone
authorDawid Kraczkowski
requires_python>=3.6,<4.0
licenseMIT
keywords troopy command command bus ddd message message bus command router
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Troopy  [![Build Status](https://travis-ci.org/kodemore/troopy.svg?branch=master)](https://travis-ci.org/kodemore/troopy)
Command bus library for python. Makes using message bus pattern in your application easy.

## What is a command/message?
Commands are objects, some kind of an imperative informing what behavior client expects from application. 
Commands can bear some information (client's input) required to fulfill the job. It is recommended to use dataclasses
when you declare a command for your own convenience.

## What is a command handler?
Command handler is a function or callable object, that accepts command as a parameter to perform specific task. 

## Advantages of using command bus/message bus

 - Command can be created anytime/anywhere by your client and as long as it is hand over to command bus it will be handled
 - You can slim your services layer and dependencies, as each handler perform one specific task
 - Testing your application can be more precise and easier

## Features

 - Fast and simple
 - Flexible solution which can be used everywhere
 - Works well with dataclasses
 - Custom factories for command handlers

## Installation

```
pip install troopy
```

# Basic Usage

```python
from troopy import CommandBus, command
from dataclasses import dataclass


class HelloHandler:
    def __call__(self, command: "SignUp") -> None:
        print("Hello user {command.username}!")


@command(HelloHandler)  # attach command to its handler
@dataclass
class SayHello:
    username: str


command_bus = CommandBus()
command_bus.dispatch(SayHello(username="Tom"))
```

`HelloHandler` is class which encapsulates our business logic (in this scenario welcomes user), any callable can be used
as a command handler, as long as it is a function or class declaration without `__init__` method.

`SayHello` is a command class which carries some data it is attached to `HelloHandler` with `@attach` decorator. 
`@attach` decorator allows the library to understand which handler is responsible for which command. It is also possible
to use `troopy.MessageRouter` directly to attach command to its handler ([example available here](/examples/custom_message_router_example.py))


The above example will print `Hello user Tom` as a result. 

# Setting factory for command handler
It is possible to use custom function for factoring command handlers, consider the following example:

```python
import sqlite3
from troopy import CommandBus, command
from dataclasses import dataclass

db = sqlite3.connect('example.db') 


class UserRegistrationHandler:
    def __init__(self, db):
        self.db = db
    def __call__(self, command: "RegisterUser") -> None:
        cursor = self.db.cursor()
        cursor.execute("INSER INTO users VALUES (?, ?)", (command.username, command.password))
        self.db.commit()


@command(UserRegistrationHandler)  # attach command to its handler
@dataclass
class RegisterUser:
    username: str
    password: str

def command_handler_factory(cls):
    return cls(db)

command_bus = CommandBus(handler_factory=command_handler_factory)
command_bus.dispatch(RegisterUser(username="Tom", password="secret"))
```

As you can probably tell `UserRegistrationHandler` requires sqlite db connection in order to work properly, with `command_handler_factory`
we are able to provide this connection to the object, so `RegisterUser` command can be handled properly.

For more examples please check [examples](/examples) directory

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/kodemore/troopy",
    "name": "troopy",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.6,<4.0",
    "maintainer_email": "",
    "keywords": "troopy,command,command bus,ddd,message,message bus,command router",
    "author": "Dawid Kraczkowski",
    "author_email": "dawid.kraczkowski@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/f8/84/67c41f3c76768d7a11d558cdc3599e1925dc2b52839a8a4deea804008bad/troopy-0.1.0.tar.gz",
    "platform": "",
    "description": "# Troopy  [![Build Status](https://travis-ci.org/kodemore/troopy.svg?branch=master)](https://travis-ci.org/kodemore/troopy)\nCommand bus library for python. Makes using message bus pattern in your application easy.\n\n## What is a command/message?\nCommands are objects, some kind of an imperative informing what behavior client expects from application. \nCommands can bear some information (client's input) required to fulfill the job. It is recommended to use dataclasses\nwhen you declare a command for your own convenience.\n\n## What is a command handler?\nCommand handler is a function or callable object, that accepts command as a parameter to perform specific task. \n\n## Advantages of using command bus/message bus\n\n - Command can be created anytime/anywhere by your client and as long as it is hand over to command bus it will be handled\n - You can slim your services layer and dependencies, as each handler perform one specific task\n - Testing your application can be more precise and easier\n\n## Features\n\n - Fast and simple\n - Flexible solution which can be used everywhere\n - Works well with dataclasses\n - Custom factories for command handlers\n\n## Installation\n\n```\npip install troopy\n```\n\n# Basic Usage\n\n```python\nfrom troopy import CommandBus, command\nfrom dataclasses import dataclass\n\n\nclass HelloHandler:\n    def __call__(self, command: \"SignUp\") -> None:\n        print(\"Hello user {command.username}!\")\n\n\n@command(HelloHandler)  # attach command to its handler\n@dataclass\nclass SayHello:\n    username: str\n\n\ncommand_bus = CommandBus()\ncommand_bus.dispatch(SayHello(username=\"Tom\"))\n```\n\n`HelloHandler` is class which encapsulates our business logic (in this scenario welcomes user), any callable can be used\nas a command handler, as long as it is a function or class declaration without `__init__` method.\n\n`SayHello` is a command class which carries some data it is attached to `HelloHandler` with `@attach` decorator. \n`@attach` decorator allows the library to understand which handler is responsible for which command. It is also possible\nto use `troopy.MessageRouter` directly to attach command to its handler ([example available here](/examples/custom_message_router_example.py))\n\n\nThe above example will print `Hello user Tom` as a result. \n\n# Setting factory for command handler\nIt is possible to use custom function for factoring command handlers, consider the following example:\n\n```python\nimport sqlite3\nfrom troopy import CommandBus, command\nfrom dataclasses import dataclass\n\ndb = sqlite3.connect('example.db') \n\n\nclass UserRegistrationHandler:\n    def __init__(self, db):\n        self.db = db\n    def __call__(self, command: \"RegisterUser\") -> None:\n        cursor = self.db.cursor()\n        cursor.execute(\"INSER INTO users VALUES (?, ?)\", (command.username, command.password))\n        self.db.commit()\n\n\n@command(UserRegistrationHandler)  # attach command to its handler\n@dataclass\nclass RegisterUser:\n    username: str\n    password: str\n\ndef command_handler_factory(cls):\n    return cls(db)\n\ncommand_bus = CommandBus(handler_factory=command_handler_factory)\ncommand_bus.dispatch(RegisterUser(username=\"Tom\", password=\"secret\"))\n```\n\nAs you can probably tell `UserRegistrationHandler` requires sqlite db connection in order to work properly, with `command_handler_factory`\nwe are able to provide this connection to the object, so `RegisterUser` command can be handled properly.\n\nFor more examples please check [examples](/examples) directory\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Command Bus/Message Bus implementation for python",
    "version": "0.1.0",
    "split_keywords": [
        "troopy",
        "command",
        "command bus",
        "ddd",
        "message",
        "message bus",
        "command router"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "md5": "819b5bf759b09499fda9081dcf966082",
                "sha256": "0bb444ffee8405f2c2b8d3bc191c2b8b540d59264105b07bc85512742d2ffe00"
            },
            "downloads": -1,
            "filename": "troopy-0.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "819b5bf759b09499fda9081dcf966082",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6,<4.0",
            "size": 4919,
            "upload_time": "2020-07-05T19:29:39",
            "upload_time_iso_8601": "2020-07-05T19:29:39.045088Z",
            "url": "https://files.pythonhosted.org/packages/67/63/215b24e1e772210a5914698e610abf9cb2406cf12505b57cc60dd2d1facf/troopy-0.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "md5": "e4f74bb1a10ad4bce6f849d413102d24",
                "sha256": "c8ab7a301c60ddb7b7b04fa336bc91ace0c85e12996be1bc6a61f807266c2ec8"
            },
            "downloads": -1,
            "filename": "troopy-0.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "e4f74bb1a10ad4bce6f849d413102d24",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6,<4.0",
            "size": 4730,
            "upload_time": "2020-07-05T19:29:40",
            "upload_time_iso_8601": "2020-07-05T19:29:40.938986Z",
            "url": "https://files.pythonhosted.org/packages/f8/84/67c41f3c76768d7a11d558cdc3599e1925dc2b52839a8a4deea804008bad/troopy-0.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2020-07-05 19:29:40",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": null,
    "github_project": "kodemore",
    "error": "Could not fetch GitHub repository",
    "lcname": "troopy"
}
        
Elapsed time: 0.09475s