# Pipable
[![ci-badge]][ci-url] [![pypi-badge]][pypi-url] [![MIT-badge]][MIT-url] [![black-badge]][black-url]
> pipe operation in python
## 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 base ** exp
# 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 variable length arguments
```python
@Pipe
def kebab(*args):
return "-".join(args)
["a", "b"] >> kebab # "a-b"
```
- use `<<` operator to pass variable 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"
```
- refer the [docs](https://hoishing.github.io/pipable/reference) for details
## 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?
use 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?
[![git-logo] github issue][github issue]
[![x-logo] posts][x-post]
[black-badge]: https://img.shields.io/badge/code%20style-black-000000.svg
[black-url]: https://github.com/psf/black
[ci-badge]: https://github.com/hoishing/pipable/actions/workflows/ci.yml/badge.svg
[ci-url]: https://github.com/hoishing/pipable/actions/workflows/ci.yml
[Coconut]: https://github.com/evhub/coconut
[git-logo]: https://api.iconify.design/bi/github.svg?color=%236FD886&width=20
[github issue]: https://github.com/hoishing/pipable/issues
[MIT-badge]: https://img.shields.io/github/license/hoishing/pipable
[MIT-url]: https://opensource.org/licenses/MIT
[pipe]: https://pypi.org/project/pipe
[pypi-badge]: https://img.shields.io/pypi/v/pipable
[pypi-url]: https://pypi.org/project/pipable/
[x-logo]: https://api.iconify.design/ri:twitter-x-fill.svg?width=20&color=DarkGray
[x-post]: https://x.com/hoishing
Raw data
{
"_id": null,
"home_page": "https://github.com/hoishing/pipable",
"name": "pipable",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.12",
"maintainer_email": null,
"keywords": "pipe, FP, functional programming, chain",
"author": "Kelvin Ng",
"author_email": "hoishing@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/9a/a8/b5cb97ac20c014dc20aad5813abe38e5a0605c18da659404e44fbe01d16e/pipable-0.3.4.tar.gz",
"platform": null,
"description": "# Pipable\n\n[![ci-badge]][ci-url] [![pypi-badge]][pypi-url] [![MIT-badge]][MIT-url] [![black-badge]][black-url]\n\n> pipe operation in python\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 base ** exp\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 variable 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 variable 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- refer the [docs](https://hoishing.github.io/pipable/reference) for details\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 \nuse 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\n[![git-logo] github issue][github issue]\n\n[![x-logo] posts][x-post]\n\n[black-badge]: https://img.shields.io/badge/code%20style-black-000000.svg\n[black-url]: https://github.com/psf/black\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[Coconut]: https://github.com/evhub/coconut\n[git-logo]: https://api.iconify.design/bi/github.svg?color=%236FD886&width=20\n[github issue]: https://github.com/hoishing/pipable/issues\n[MIT-badge]: https://img.shields.io/github/license/hoishing/pipable\n[MIT-url]: https://opensource.org/licenses/MIT\n[pipe]: https://pypi.org/project/pipe\n[pypi-badge]: https://img.shields.io/pypi/v/pipable\n[pypi-url]: https://pypi.org/project/pipable/\n[x-logo]: https://api.iconify.design/ri:twitter-x-fill.svg?width=20&color=DarkGray\n[x-post]: https://x.com/hoishing\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "pseudo pipe operation in python",
"version": "0.3.4",
"project_urls": {
"Documentation": "https://hoishing.github.io/pipable",
"Homepage": "https://github.com/hoishing/pipable",
"Repository": "https://github.com/hoishing/pipable"
},
"split_keywords": [
"pipe",
" fp",
" functional programming",
" chain"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "cc6cd41ee88a756aa6fe4039ef06877472e9c3e9edbcd9e3bd6f48877981d1dc",
"md5": "fe41ff82b698a780ea55c53f0d317e56",
"sha256": "30b504f44081da56f4830bfffc3d2c80e611365a13c37fa7ea75e884b7bcf9b3"
},
"downloads": -1,
"filename": "pipable-0.3.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "fe41ff82b698a780ea55c53f0d317e56",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.12",
"size": 4324,
"upload_time": "2024-10-05T03:11:05",
"upload_time_iso_8601": "2024-10-05T03:11:05.998807Z",
"url": "https://files.pythonhosted.org/packages/cc/6c/d41ee88a756aa6fe4039ef06877472e9c3e9edbcd9e3bd6f48877981d1dc/pipable-0.3.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "9aa8b5cb97ac20c014dc20aad5813abe38e5a0605c18da659404e44fbe01d16e",
"md5": "d97490ea44bed9004bf319142d239ffb",
"sha256": "78329ad961cad82bf418e2cc1d4768aa45a76c60e96987983f1212bba5e81c54"
},
"downloads": -1,
"filename": "pipable-0.3.4.tar.gz",
"has_sig": false,
"md5_digest": "d97490ea44bed9004bf319142d239ffb",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.12",
"size": 3893,
"upload_time": "2024-10-05T03:11:07",
"upload_time_iso_8601": "2024-10-05T03:11:07.511251Z",
"url": "https://files.pythonhosted.org/packages/9a/a8/b5cb97ac20c014dc20aad5813abe38e5a0605c18da659404e44fbe01d16e/pipable-0.3.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-05 03:11:07",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "hoishing",
"github_project": "pipable",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "pipable"
}