lz
==
[![](https://github.com/lycantropos/lz/workflows/CI/badge.svg)](https://github.com/lycantropos/lz/actions/workflows/ci.yml "Github Actions")
[![](https://codecov.io/gh/lycantropos/lz/branch/master/graph/badge.svg)](https://codecov.io/gh/lycantropos/lz "Codecov")
[![](https://readthedocs.org/projects/lz/badge/?version=latest)](https://lz.readthedocs.io/en/latest "Documentation")
[![](https://img.shields.io/github/license/lycantropos/lz.svg)](https://github.com/lycantropos/lz/blob/master/LICENSE "License")
[![](https://badge.fury.io/py/lz.svg)](https://badge.fury.io/py/lz "PyPI")
In what follows `python` is an alias for `python3.7` or `pypy3.7`
or any later version (`python3.8`, `pypy3.8` and so on).
Installation
------------
Install the latest `pip` & `setuptools` packages versions
```bash
python -m pip install --upgrade pip setuptools
```
### User
Download and install the latest stable version from `PyPI` repository
```bash
python -m pip install --upgrade lz
```
### Developer
Download the latest version from `GitHub` repository
```bash
git clone https://github.com/lycantropos/lz.git
cd lz
```
Install dependencies
```bash
python -m pip install -r requirements.txt
```
Install
```bash
python setup.py install
```
Usage
-----
`lz` provides a bunch of utilities for working with functions, predicates & iterables such as
1. [function composition](https://en.wikipedia.org/wiki/Function_composition)
```python
>>> from lz.functional import compose
>>> sum_of_first_n_natural_numbers = compose(sum, range)
>>> sum_of_first_n_natural_numbers(10)
45
```
2. [currying](https://en.wikipedia.org/wiki/Currying)
```python
>>> from lz.functional import curry
>>> curried_power = curry(pow)
>>> two_to_power = curried_power(2)
>>> two_to_power(10)
1024
```
3. flipping positional parameters order
```python
>>> from lz.functional import flip
>>> flipped_power = flip(pow)
>>> flipped_power(2, 3)
9
```
4. packing function's arguments
```python
>>> from lz.functional import pack
>>> packed_int = pack(int)
>>> packed_int(['10'])
10
>>> packed_int(['10'], {'base': 2})
2
```
5. left [partial application](https://en.wikipedia.org/wiki/Partial_application)
```python
>>> from lz import left
>>> count_from_zero_to = left.applier(range, 0)
>>> list(count_from_zero_to(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
```
6. right [partial application](https://en.wikipedia.org/wiki/Partial_application)
```python
>>> from lz import right
>>> square = right.applier(pow, 2)
>>> square(10)
100
```
7. [negating](https://en.wikipedia.org/wiki/Negation) predicate
```python
>>> from lz.logical import negate
>>> false_like = negate(bool)
>>> false_like([])
True
>>> false_like([0])
False
```
8. [conjoining](https://en.wikipedia.org/wiki/Logical_conjunction) predicates
```python
>>> from lz.logical import conjoin
>>> is_valid_constant_identifier = conjoin(str.isupper, str.isidentifier)
>>> is_valid_constant_identifier('SECOND_SECTION')
True
>>> is_valid_constant_identifier('2ND_SECTION')
False
```
9. [disjoining](https://en.wikipedia.org/wiki/Logical_disjunction) predicates
```python
>>> from lz.logical import disjoin
>>> alphabetic_or_numeric = disjoin(str.isalpha, str.isnumeric)
>>> alphabetic_or_numeric('Hello')
True
>>> alphabetic_or_numeric('42')
True
>>> alphabetic_or_numeric('Hello42')
False
```
10. [exclusive disjoining](https://en.wikipedia.org/wiki/Exclusive_or) predicates
```python
>>> from lz.logical import exclusive_disjoin
>>> from keyword import iskeyword
>>> valid_object_name = exclusive_disjoin(str.isidentifier, iskeyword)
>>> valid_object_name('valid_object_name')
True
>>> valid_object_name('_')
True
>>> valid_object_name('1')
False
>>> valid_object_name('lambda')
False
```
11. reversing sequences and any string streams
```python
>>> from lz.reversal import reverse
>>> list(reverse(range(10)))
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> import io
>>> list(reverse(io.BytesIO(b'Hello\nWorld!')))
[b'World!', b'Hello\n']
```
12. chunking iterable
```python
>>> from lz.iterating import chopper
>>> to_triplets = chopper(3)
>>> list(map(tuple, to_triplets(range(10))))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9,)]
```
13. sliding over iterable
```python
>>> from lz.iterating import slider
>>> slide_pairwise = slider(2)
>>> list(slide_pairwise(range(10)))
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)]
```
14. [interleaving](https://en.wikipedia.org/wiki/Interleave_sequence) iterables
```python
>>> from lz.iterating import interleave
>>> list(interleave([range(10), range(10, 20)]))
[0, 10, 1, 11, 2, 12, 3, 13, 4, 14, 5, 15, 6, 16, 7, 17, 8, 18, 9, 19]
```
15. iterable [transposition](https://en.wikipedia.org/wiki/Transpose)
```python
>>> from lz.transposition import transpose
>>> list(map(tuple, transpose(zip(range(10), range(10, 20)))))
[(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), (10, 11, 12, 13, 14, 15, 16, 17, 18, 19)]
```
16. iterable duplication
```python
>>> from lz.replication import duplicate
>>> list(map(tuple, duplicate(range(10))))
[(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)]
```
and [many more](https://lz.readthedocs.io/en/latest).
Development
-----------
### Building docs
Install project in editable mode
```bash
python -m pip install -e .
```
Install dependencies
```bash
python -m pip install -r docs/requirements.txt
```
Build docs
```bash
cd docs
make html
```
### Bumping version
#### Preparation
Install
[bump2version](https://github.com/c4urself/bump2version#installation).
#### Pre-release
Choose which version number category to bump following [semver
specification](http://semver.org/).
Test bumping version
```bash
bump2version --dry-run --verbose $CATEGORY
```
where `$CATEGORY` is the target version number category name, possible
values are `patch`/`minor`/`major`.
Bump version
```bash
bump2version --verbose $CATEGORY
```
This will set version to `major.minor.patch-alpha`.
#### Release
Test bumping version
```bash
bump2version --dry-run --verbose release
```
Bump version
```bash
bump2version --verbose release
```
This will set version to `major.minor.patch`.
### Running tests
Install dependencies
```bash
python -m pip install -r requirements-tests.txt
```
Plain
```bash
pytest
```
Inside `Docker` container:
- with `CPython`
```bash
docker-compose --file docker-compose.cpython.yml up
```
- with `PyPy`
```bash
docker-compose --file docker-compose.pypy.yml up
```
`Bash` script (e.g. can be used in `Git` hooks):
- with `CPython`
```bash
./run-tests.sh
```
or
```bash
./run-tests.sh cpython
```
- with `PyPy`
```bash
./run-tests.sh pypy
```
`PowerShell` script (e.g. can be used in `Git` hooks):
- with `CPython`
```powershell
.\run-tests.ps1
```
or
```powershell
.\run-tests.ps1 cpython
```
- with `PyPy`
```powershell
.\run-tests.ps1 pypy
```
Raw data
{
"_id": null,
"home_page": "https://github.com/lycantropos/lz/",
"name": "lz",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "",
"keywords": "",
"author": "Azat Ibrakov",
"author_email": "azatibrakov@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/6f/ea/41f32f27a1a8678597ac526df4348aa1905771779a06b799f21c7c2c20d6/lz-2.0.0.tar.gz",
"platform": null,
"description": "lz\n==\n\n[![](https://github.com/lycantropos/lz/workflows/CI/badge.svg)](https://github.com/lycantropos/lz/actions/workflows/ci.yml \"Github Actions\")\n[![](https://codecov.io/gh/lycantropos/lz/branch/master/graph/badge.svg)](https://codecov.io/gh/lycantropos/lz \"Codecov\")\n[![](https://readthedocs.org/projects/lz/badge/?version=latest)](https://lz.readthedocs.io/en/latest \"Documentation\")\n[![](https://img.shields.io/github/license/lycantropos/lz.svg)](https://github.com/lycantropos/lz/blob/master/LICENSE \"License\")\n[![](https://badge.fury.io/py/lz.svg)](https://badge.fury.io/py/lz \"PyPI\")\n\nIn what follows `python` is an alias for `python3.7` or `pypy3.7`\nor any later version (`python3.8`, `pypy3.8` and so on).\n\nInstallation\n------------\n\nInstall the latest `pip` & `setuptools` packages versions\n```bash\npython -m pip install --upgrade pip setuptools\n```\n\n### User\n\nDownload and install the latest stable version from `PyPI` repository\n```bash\npython -m pip install --upgrade lz\n```\n\n### Developer\n\nDownload the latest version from `GitHub` repository\n```bash\ngit clone https://github.com/lycantropos/lz.git\ncd lz\n```\n\nInstall dependencies\n```bash\npython -m pip install -r requirements.txt\n```\n\nInstall\n```bash\npython setup.py install\n```\n\nUsage \n----- \n \n`lz` provides a bunch of utilities for working with functions, predicates & iterables such as\n\n1. [function composition](https://en.wikipedia.org/wiki/Function_composition)\n ```python\n >>> from lz.functional import compose\n >>> sum_of_first_n_natural_numbers = compose(sum, range)\n >>> sum_of_first_n_natural_numbers(10)\n 45\n\n ```\n\n2. [currying](https://en.wikipedia.org/wiki/Currying)\n ```python\n >>> from lz.functional import curry \n >>> curried_power = curry(pow) \n >>> two_to_power = curried_power(2) \n >>> two_to_power(10)\n 1024\n\n ```\n\n3. flipping positional parameters order\n ```python\n >>> from lz.functional import flip\n >>> flipped_power = flip(pow)\n >>> flipped_power(2, 3)\n 9\n\n ```\n\n4. packing function's arguments\n ```python\n >>> from lz.functional import pack\n >>> packed_int = pack(int)\n >>> packed_int(['10'])\n 10\n >>> packed_int(['10'], {'base': 2})\n 2\n\n ```\n\n5. left [partial application](https://en.wikipedia.org/wiki/Partial_application)\n ```python\n >>> from lz import left\n >>> count_from_zero_to = left.applier(range, 0)\n >>> list(count_from_zero_to(10))\n [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n\n ```\n\n6. right [partial application](https://en.wikipedia.org/wiki/Partial_application)\n ```python\n >>> from lz import right\n >>> square = right.applier(pow, 2)\n >>> square(10)\n 100\n\n ```\n\n7. [negating](https://en.wikipedia.org/wiki/Negation) predicate\n ```python\n >>> from lz.logical import negate\n >>> false_like = negate(bool)\n >>> false_like([])\n True\n >>> false_like([0])\n False\n\n ```\n\n8. [conjoining](https://en.wikipedia.org/wiki/Logical_conjunction) predicates\n ```python\n >>> from lz.logical import conjoin\n >>> is_valid_constant_identifier = conjoin(str.isupper, str.isidentifier)\n >>> is_valid_constant_identifier('SECOND_SECTION')\n True\n >>> is_valid_constant_identifier('2ND_SECTION')\n False\n\n ```\n\n9. [disjoining](https://en.wikipedia.org/wiki/Logical_disjunction) predicates\n ```python\n >>> from lz.logical import disjoin\n >>> alphabetic_or_numeric = disjoin(str.isalpha, str.isnumeric)\n >>> alphabetic_or_numeric('Hello')\n True\n >>> alphabetic_or_numeric('42')\n True\n >>> alphabetic_or_numeric('Hello42')\n False\n\n ```\n\n10. [exclusive disjoining](https://en.wikipedia.org/wiki/Exclusive_or) predicates\n ```python\n >>> from lz.logical import exclusive_disjoin\n >>> from keyword import iskeyword\n >>> valid_object_name = exclusive_disjoin(str.isidentifier, iskeyword)\n >>> valid_object_name('valid_object_name')\n True\n >>> valid_object_name('_')\n True\n >>> valid_object_name('1')\n False\n >>> valid_object_name('lambda')\n False\n\n ```\n\n11. reversing sequences and any string streams\n ```python\n >>> from lz.reversal import reverse\n >>> list(reverse(range(10)))\n [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]\n >>> import io\n >>> list(reverse(io.BytesIO(b'Hello\\nWorld!')))\n [b'World!', b'Hello\\n']\n\n ```\n\n12. chunking iterable\n ```python\n >>> from lz.iterating import chopper\n >>> to_triplets = chopper(3)\n >>> list(map(tuple, to_triplets(range(10))))\n [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9,)]\n\n ```\n\n13. sliding over iterable\n ```python\n >>> from lz.iterating import slider\n >>> slide_pairwise = slider(2)\n >>> list(slide_pairwise(range(10)))\n [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)]\n \n ```\n\n14. [interleaving](https://en.wikipedia.org/wiki/Interleave_sequence) iterables\n ```python\n >>> from lz.iterating import interleave\n >>> list(interleave([range(10), range(10, 20)]))\n [0, 10, 1, 11, 2, 12, 3, 13, 4, 14, 5, 15, 6, 16, 7, 17, 8, 18, 9, 19]\n \n ```\n\n15. iterable [transposition](https://en.wikipedia.org/wiki/Transpose)\n ```python\n >>> from lz.transposition import transpose\n >>> list(map(tuple, transpose(zip(range(10), range(10, 20)))))\n [(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), (10, 11, 12, 13, 14, 15, 16, 17, 18, 19)]\n \n ```\n\n16. iterable duplication\n ```python\n >>> from lz.replication import duplicate\n >>> list(map(tuple, duplicate(range(10))))\n [(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)]\n \n ```\n\nand [many more](https://lz.readthedocs.io/en/latest).\n\nDevelopment\n-----------\n\n### Building docs\n\nInstall project in editable mode\n```bash\npython -m pip install -e .\n```\n\nInstall dependencies\n```bash\npython -m pip install -r docs/requirements.txt\n```\n\nBuild docs\n```bash\ncd docs\nmake html\n```\n\n### Bumping version\n\n#### Preparation\n\nInstall\n[bump2version](https://github.com/c4urself/bump2version#installation).\n\n#### Pre-release\n\nChoose which version number category to bump following [semver\nspecification](http://semver.org/).\n\nTest bumping version\n```bash\nbump2version --dry-run --verbose $CATEGORY\n```\n\nwhere `$CATEGORY` is the target version number category name, possible\nvalues are `patch`/`minor`/`major`.\n\nBump version\n```bash\nbump2version --verbose $CATEGORY\n```\n\nThis will set version to `major.minor.patch-alpha`. \n\n#### Release\n\nTest bumping version\n```bash\nbump2version --dry-run --verbose release\n```\n\nBump version\n```bash\nbump2version --verbose release\n```\n\nThis will set version to `major.minor.patch`.\n\n### Running tests\n\nInstall dependencies\n```bash\npython -m pip install -r requirements-tests.txt\n```\n\nPlain\n```bash\npytest\n```\n\nInside `Docker` container:\n- with `CPython`\n ```bash\n docker-compose --file docker-compose.cpython.yml up\n ```\n- with `PyPy`\n ```bash\n docker-compose --file docker-compose.pypy.yml up\n ```\n\n`Bash` script (e.g. can be used in `Git` hooks):\n- with `CPython`\n ```bash\n ./run-tests.sh\n ```\n or\n ```bash\n ./run-tests.sh cpython\n ```\n\n- with `PyPy`\n ```bash\n ./run-tests.sh pypy\n ```\n\n`PowerShell` script (e.g. can be used in `Git` hooks):\n- with `CPython`\n ```powershell\n .\\run-tests.ps1\n ```\n or\n ```powershell\n .\\run-tests.ps1 cpython\n ```\n- with `PyPy`\n ```powershell\n .\\run-tests.ps1 pypy\n ```\n",
"bugtrack_url": null,
"license": "MIT License",
"summary": "\"Lazy\" calculations support.",
"version": "2.0.0",
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "14653c00a06fddf5f91339dfef9694d3798daba647a8e95e8d59e78146c0e090",
"md5": "5296dbac011f1481c149a25948e40745",
"sha256": "0a4d4d1c3b3444054a3e8a49eb9b62078afce96d78331fab593742c484b50939"
},
"downloads": -1,
"filename": "lz-2.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "5296dbac011f1481c149a25948e40745",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 24799,
"upload_time": "2023-01-11T01:55:32",
"upload_time_iso_8601": "2023-01-11T01:55:32.581152Z",
"url": "https://files.pythonhosted.org/packages/14/65/3c00a06fddf5f91339dfef9694d3798daba647a8e95e8d59e78146c0e090/lz-2.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "6fea41f32f27a1a8678597ac526df4348aa1905771779a06b799f21c7c2c20d6",
"md5": "d104fc8acfdb1608e5c89db8c437a93d",
"sha256": "6a84132bb968aa5dc09ea7ac480a0542b8d038e5baf4cd8e7980255d270d7c66"
},
"downloads": -1,
"filename": "lz-2.0.0.tar.gz",
"has_sig": false,
"md5_digest": "d104fc8acfdb1608e5c89db8c437a93d",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 21259,
"upload_time": "2023-01-11T01:55:33",
"upload_time_iso_8601": "2023-01-11T01:55:33.972613Z",
"url": "https://files.pythonhosted.org/packages/6f/ea/41f32f27a1a8678597ac526df4348aa1905771779a06b799f21c7c2c20d6/lz-2.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-01-11 01:55:33",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "lycantropos",
"github_project": "lz",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"requirements": [
{
"name": "paradigm",
"specs": [
[
">=",
"3.0.0"
],
[
"<",
"4.0"
]
]
},
{
"name": "reprit",
"specs": [
[
">=",
"0.8.0"
],
[
"<",
"1.0"
]
]
},
{
"name": "typing_extensions",
"specs": [
[
">=",
"4.4.0"
],
[
"<",
"5.0"
]
]
}
],
"lcname": "lz"
}