pipable


Namepipable JSON
Version 0.3.1 PyPI version JSON
download
home_pagehttps://hoishing.github.io/pipable
Summarypseudo pipe operation in python
upload_time2023-02-09 18:29:24
maintainer
docs_urlNone
authorKelvin Ng
requires_python>=3.8,<4.0
licenseMIT
keywords pipe fp functional programming chain
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # pipable

[![ci-badge]][ci-url] [![coverage-badge]][coverage-url] [![pypi-badge]][pypi-url] ![py-ver-badge] [![MIT-badge]][MIT-url] [![black-badge]][black-url]

> pipe operation in python

🔗 [source code](https://github.com/hoishing/pipable)

## Quick Start

### Create the Pipe Object

- instantiate with the `Pipe` class

```python
from pipable import Pipe

list = Pipe(list)
"abc" | list    # ["a", "b", "c"]
```

#### Pipe Object is Partial with Infix Operator

- at the core Pipe create partial function while overriding it's `|` operator
- instantiate Pipe object like the built-in `functools.partial`
- preceding output will be assigned to the last positional argument of the Pipe object

```python
square = Pipe(pow, exp=2)
3 | square    # 9
```

Since that Pipe appends preceding output to the last positional argument,
assigning 1st argument with keyword will raise exception.
This behave the same as `functools.partial`

```python
base2 = Pipe(pow, 2)  # positional arg ok
3 | base2    # 8

base2 = Pipe(pow, base=2)  # keyword arg don't
3 | base2    # raise!!
```

### Using Decorator

- `@Pipe` decorator transforms function into Pipe object
- preceding output will be assigned to the last positional argument
- instantiate Pipe decorated function similar to creating partial

```python
# only one argument
@Pipe
def hi(name: str) -> str:
  return f"hi {name}"

"May" | hi    # "hi May"


# multiple arguments
@Pipe
def power(base: int, exp: int) -> int:
  return a ** b

# instantiate Pipe obj by partially calling the function
2 | power(3)        # 9, note we need to use positional argument here
2 | power(exp=3)    # 8, subsequent arguments can use keyword

# assign the 1st argument with keyword will raise exception
2 | power(base=3)    # raise !!
```

### Passing Variable Length Arguments

- use `>>` operator to pass-in var length arguments

```python
@Pipe
def kebab(*args):
    return "-".join(args)

["a", "b"] >> kebab   # "a-b"
```

- use `<<` operator to pass var length keyword arguments

```python
@Pipe
def concat(**kwargs):
    return ", ".join([f"{k}-{v}" for k, v in kwargs.items()])

dict(b="boy", c="cat") << concat    # "b-boy, c-cat"
```

## Motivation

Pipe operation is a handy feature in functional programming. It allows us to:

- write more succinct and readable code
- create less variables
- easily create new function by chaining other functions

However it's still a missing feature in Python as of 2023. This package try to mimic pipe operation by overriding the bitwise-or operator, and turn any function into pipable partial.

There are packages, such as [pipe] take the similar approach. It works great with iterables, and create pipe as iterator, ie. open pipe). However, I simply want to take preceding expression as an input argument of the current function then execute it, ie. close pipe. It leads to the creation of this package.

## FAQ

How can I assign value to the first argument?
  
Assign it within a wrapper function

```python
square = Pipe(lambda x: pow(x, 2))
3 | square  # 9
```

---

Can I create open pipe?

`Pipe` only create closed pipe, ie. execute the function after piping with the `|` operator. You may consider other solutions such as:

- [pipe], which create open pipe for iterators
- [Coconut], a python variant that embrace functional programming

---

Can I append the preceding output at the beginning of the argument list?

Put the preceding output as the 1st argument of a wrapper function

```python
# prepend is the default behaviour
def kebab(*args):
  return "-".join(*args)

'a' | Pipe(kebab, 'b', 'c')  # 'b c a'

@Pipe
def wrapper(first, others):
  return kebab(first, *others)

'a' | wrapper(others=['b', 'c'])  # 'a b c'
```

## Need Help?

Open a [github issue] or ping me on [Twitter ![twitter-icon]][Twitter]

[github issue]: https://github.com/hoishing/pipable/issues
[Twitter]: https://twitter.com/hoishing
[twitter-icon]: https://api.iconify.design/logos/twitter.svg?width=20
[ci-badge]: https://github.com/hoishing/pipable/actions/workflows/ci.yml/badge.svg
[ci-url]: https://github.com/hoishing/pipable/actions/workflows/ci.yml
[coverage-badge]: https://hoishing.github.io/pipable/assets/coverage-badge.svg
[coverage-url]: https://hoishing.github.io/pipable/assets/coverage/
[MIT-badge]: https://img.shields.io/github/license/hoishing/pipable
[MIT-url]: https://opensource.org/licenses/MIT
[pypi-badge]: https://img.shields.io/pypi/v/pipable
[pypi-url]: https://pypi.org/project/pipable/
[black-badge]: https://img.shields.io/badge/code%20style-black-000000.svg
[black-url]: https://github.com/psf/black
[py-ver-badge]: https://img.shields.io/pypi/pyversions/pipable
[pipe]: https://pypi.org/project/pipe
[Coconut]: https://github.com/evhub/coconut

            

Raw data

            {
    "_id": null,
    "home_page": "https://hoishing.github.io/pipable",
    "name": "pipable",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8,<4.0",
    "maintainer_email": "",
    "keywords": "pipe,FP,functional programming,chain",
    "author": "Kelvin Ng",
    "author_email": "hoishing@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/70/f4/128ac255b428df75b76403ea58bf08673217570666e464ee2a0fdd672047/pipable-0.3.1.tar.gz",
    "platform": null,
    "description": "# pipable\n\n[![ci-badge]][ci-url] [![coverage-badge]][coverage-url] [![pypi-badge]][pypi-url] ![py-ver-badge] [![MIT-badge]][MIT-url] [![black-badge]][black-url]\n\n> pipe operation in python\n\n\ud83d\udd17 [source code](https://github.com/hoishing/pipable)\n\n## Quick Start\n\n### Create the Pipe Object\n\n- instantiate with the `Pipe` class\n\n```python\nfrom pipable import Pipe\n\nlist = Pipe(list)\n\"abc\" | list    # [\"a\", \"b\", \"c\"]\n```\n\n#### Pipe Object is Partial with Infix Operator\n\n- at the core Pipe create partial function while overriding it's `|` operator\n- instantiate Pipe object like the built-in `functools.partial`\n- preceding output will be assigned to the last positional argument of the Pipe object\n\n```python\nsquare = Pipe(pow, exp=2)\n3 | square    # 9\n```\n\nSince that Pipe appends preceding output to the last positional argument,\nassigning 1st argument with keyword will raise exception.\nThis behave the same as `functools.partial`\n\n```python\nbase2 = Pipe(pow, 2)  # positional arg ok\n3 | base2    # 8\n\nbase2 = Pipe(pow, base=2)  # keyword arg don't\n3 | base2    # raise!!\n```\n\n### Using Decorator\n\n- `@Pipe` decorator transforms function into Pipe object\n- preceding output will be assigned to the last positional argument\n- instantiate Pipe decorated function similar to creating partial\n\n```python\n# only one argument\n@Pipe\ndef hi(name: str) -> str:\n  return f\"hi {name}\"\n\n\"May\" | hi    # \"hi May\"\n\n\n# multiple arguments\n@Pipe\ndef power(base: int, exp: int) -> int:\n  return a ** b\n\n# instantiate Pipe obj by partially calling the function\n2 | power(3)        # 9, note we need to use positional argument here\n2 | power(exp=3)    # 8, subsequent arguments can use keyword\n\n# assign the 1st argument with keyword will raise exception\n2 | power(base=3)    # raise !!\n```\n\n### Passing Variable Length Arguments\n\n- use `>>` operator to pass-in var length arguments\n\n```python\n@Pipe\ndef kebab(*args):\n    return \"-\".join(args)\n\n[\"a\", \"b\"] >> kebab   # \"a-b\"\n```\n\n- use `<<` operator to pass var length keyword arguments\n\n```python\n@Pipe\ndef concat(**kwargs):\n    return \", \".join([f\"{k}-{v}\" for k, v in kwargs.items()])\n\ndict(b=\"boy\", c=\"cat\") << concat    # \"b-boy, c-cat\"\n```\n\n## Motivation\n\nPipe operation is a handy feature in functional programming. It allows us to:\n\n- write more succinct and readable code\n- create less variables\n- easily create new function by chaining other functions\n\nHowever it's still a missing feature in Python as of 2023. This package try to mimic pipe operation by overriding the bitwise-or operator, and turn any function into pipable partial.\n\nThere are packages, such as [pipe] take the similar approach. It works great with iterables, and create pipe as iterator, ie. open pipe). However, I simply want to take preceding expression as an input argument of the current function then execute it, ie. close pipe. It leads to the creation of this package.\n\n## FAQ\n\nHow can I assign value to the first argument?\n  \nAssign it within a wrapper function\n\n```python\nsquare = Pipe(lambda x: pow(x, 2))\n3 | square  # 9\n```\n\n---\n\nCan I create open pipe?\n\n`Pipe` only create closed pipe, ie. execute the function after piping with the `|` operator. You may consider other solutions such as:\n\n- [pipe], which create open pipe for iterators\n- [Coconut], a python variant that embrace functional programming\n\n---\n\nCan I append the preceding output at the beginning of the argument list?\n\nPut the preceding output as the 1st argument of a wrapper function\n\n```python\n# prepend is the default behaviour\ndef kebab(*args):\n  return \"-\".join(*args)\n\n'a' | Pipe(kebab, 'b', 'c')  # 'b c a'\n\n@Pipe\ndef wrapper(first, others):\n  return kebab(first, *others)\n\n'a' | wrapper(others=['b', 'c'])  # 'a b c'\n```\n\n## Need Help?\n\nOpen a [github issue] or ping me on [Twitter ![twitter-icon]][Twitter]\n\n[github issue]: https://github.com/hoishing/pipable/issues\n[Twitter]: https://twitter.com/hoishing\n[twitter-icon]: https://api.iconify.design/logos/twitter.svg?width=20\n[ci-badge]: https://github.com/hoishing/pipable/actions/workflows/ci.yml/badge.svg\n[ci-url]: https://github.com/hoishing/pipable/actions/workflows/ci.yml\n[coverage-badge]: https://hoishing.github.io/pipable/assets/coverage-badge.svg\n[coverage-url]: https://hoishing.github.io/pipable/assets/coverage/\n[MIT-badge]: https://img.shields.io/github/license/hoishing/pipable\n[MIT-url]: https://opensource.org/licenses/MIT\n[pypi-badge]: https://img.shields.io/pypi/v/pipable\n[pypi-url]: https://pypi.org/project/pipable/\n[black-badge]: https://img.shields.io/badge/code%20style-black-000000.svg\n[black-url]: https://github.com/psf/black\n[py-ver-badge]: https://img.shields.io/pypi/pyversions/pipable\n[pipe]: https://pypi.org/project/pipe\n[Coconut]: https://github.com/evhub/coconut\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "pseudo pipe operation in python",
    "version": "0.3.1",
    "split_keywords": [
        "pipe",
        "fp",
        "functional programming",
        "chain"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "07d66c7d54155f546e6598ef246a74adacfc41dea24fb433829ba2594629a01d",
                "md5": "613265b832a9fabd02d9dd56b0dc6307",
                "sha256": "5e1e3794b38150752d369f646827a8237b5bddc0acef756f67ad03bc222e4c8c"
            },
            "downloads": -1,
            "filename": "pipable-0.3.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "613265b832a9fabd02d9dd56b0dc6307",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8,<4.0",
            "size": 4592,
            "upload_time": "2023-02-09T18:29:23",
            "upload_time_iso_8601": "2023-02-09T18:29:23.218113Z",
            "url": "https://files.pythonhosted.org/packages/07/d6/6c7d54155f546e6598ef246a74adacfc41dea24fb433829ba2594629a01d/pipable-0.3.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "70f4128ac255b428df75b76403ea58bf08673217570666e464ee2a0fdd672047",
                "md5": "7e74f938fe28317f9d075adfce60aa8c",
                "sha256": "911add478f68d277b24ccc9b78cb1b87271e970bacfdf6a2c28bc7b2f400b56e"
            },
            "downloads": -1,
            "filename": "pipable-0.3.1.tar.gz",
            "has_sig": false,
            "md5_digest": "7e74f938fe28317f9d075adfce60aa8c",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8,<4.0",
            "size": 4837,
            "upload_time": "2023-02-09T18:29:24",
            "upload_time_iso_8601": "2023-02-09T18:29:24.860821Z",
            "url": "https://files.pythonhosted.org/packages/70/f4/128ac255b428df75b76403ea58bf08673217570666e464ee2a0fdd672047/pipable-0.3.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-02-09 18:29:24",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "lcname": "pipable"
}
        
Elapsed time: 0.03920s