diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dc64ba9..9caeab0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,7 +82,7 @@ jobs: run: python -m twine upload dist/* - name: Github Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 mkdocs-github-pages: if: "!startsWith(github.ref, 'refs/tags/')" @@ -93,7 +93,7 @@ jobs: - uses: actions/setup-python@v5 with: python-version: 3.12 - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: key: ${{ github.ref }} path: .cache diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d382642..248a001 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ ci: autoupdate_schedule: quarterly repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: check-added-large-files - id: check-yaml @@ -29,19 +29,19 @@ repos: - id: add-trailing-comma - repo: https://github.com/asottile/pyupgrade - rev: v3.15.0 + rev: v3.15.2 hooks: - id: pyupgrade args: [--py311-plus] - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.1.7 + rev: v0.3.7 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] - repo: https://github.com/PyCQA/pylint - rev: v3.0.1 + rev: v3.1.0 hooks: - id: pylint additional_dependencies: ["pylint-per-file-ignores"] @@ -52,7 +52,7 @@ repos: # - id: autopep8 - repo: https://github.com/PyCQA/flake8 - rev: 6.1.0 + rev: 7.0.0 hooks: - id: flake8 additional_dependencies: [Flake8-pyproject] diff --git a/docs/reference.md b/docs/reference.md index b691329..78fa2cd 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -203,6 +203,14 @@ Same as `FilterKeys` but for `v` in `(k, v)` pairs ``` +## SwapKV + +```py +>>> [(0, 1), (2, 3)] | SwapKV() | Pipe(list) +[(1, 0), (3, 2)] + +``` + ## Grep ```py diff --git a/docs/similar-tools.md b/docs/similar-tools.md index e41acb9..821908b 100644 --- a/docs/similar-tools.md +++ b/docs/similar-tools.md @@ -31,3 +31,5 @@ - [petl-developers/petl: Python Extract Transform and Load Tables of Data](https://github.com/petl-developers/petl) - [Show HN: Pypipe – A Python command-line tool for pipeline processing | Hacker News](https://news.ycombinator.com/item?id=37981683) - [Marcel the Shell | Hacker News](https://news.ycombinator.com/item?id=37991746) +- [cgarciae/pypeln: Concurrent data pipelines in Python >>>](https://github.com/cgarciae/pypeln) +- [sfermigier/awesome-functional-python: A curated list of awesome things related to functional programming in Python.](https://github.com/sfermigier/awesome-functional-python) diff --git a/pipe21.py b/pipe21.py index ef57d42..635e124 100644 --- a/pipe21.py +++ b/pipe21.py @@ -30,6 +30,7 @@ class ValueBy (B): __ror__ = lambda self, it: ((x, self.f(x)) for x in it) class Append (B): __ror__ = lambda self, it: ((*x, self.f(x)) for x in it) class Keys (B): __ror__ = lambda self, it: (k for k, v in it) class Values (B): __ror__ = lambda self, it: (v for k, v in it) +class SwapKV (B): __ror__ = lambda self, it: it | Map(operator.itemgetter(1, 0)) class Grep (B): __ror__ = lambda self, it: it | (FilterFalse if self.kw.get('v', False) else Filter)(re.compile(self.f, flags=re.IGNORECASE if self.kw.get('i', False) else 0).search) class IterLines (B): __ror__ = lambda self, f: (x.strip() if self.kw.get('strip', True) else x for x in open(f)) class Count (B): __ror__ = lambda self, it: sum(1 for _ in it) diff --git a/tests/pipe_test.py b/tests/pipe_test.py index 9f9e6e8..5bad4d0 100644 --- a/tests/pipe_test.py +++ b/tests/pipe_test.py @@ -167,6 +167,15 @@ def test_values(it, expected): assert it | Values() | Pipe(list) == expected +@pytest.mark.parametrize( + ('it', 'expected'), [ + ([(0, 1), (2, 3)], [(1, 0), (3, 2)]), + ], +) +def test_swap_kv(it, expected): + assert it | SwapKV() | Pipe(list) == expected + + @pytest.mark.parametrize( ('it', 'grep', 'expected'), [ (['hello foo', 'world', 'awesome FOo'], 'foo', ['hello foo']),