If Funcy and Pipe had a baby. Decorates all Funcy methods with Pipe superpowers.
Project description
Funcy with pipeline-based operators
If Funcy and Pipe had a baby. Deal with data transformation in python in a sane way.
I love Ruby, but believe Python is the way of the future. As I worked more with Python, it was driving me nuts that the data transformation options were not chainable like Ruby + Elixir. This project fixes this pet peeve.
Examples
import funcy_pipe as fp
entities_from_sql_alchemy
| fp.lmap(lambda r: r.to_dict())
| fp.lmap(lambda r: r | fp.omit(["id", "created_at", "updated_at"]))
| fp.to_list
Or, you can be more fancy and use whatever and pmap
:
import funcy_pipe as f
import whatever as _
entities_from_sql_alchemy
| fp.lmap(_.to_dict)
| fp.pmap(fp.omit(["id", "created_at", "updated_at"]))
| fp.to_list
Grab the ID of a specific user:
filter_user_id = (
collaborator_map().values()
| fp.where(email=target_user)
| fp.pluck("id")
| fp.first()
)
What if the objects are not dicts?
filter_user_id = (
collaborator_map().values()
| fp.where_attr(email=target_user)
| fp.pluck_attr("id")
| fp.first()
)
A more complicated example (lifted from this project):
comments = (
# tasks are pulled from the todoist api
tasks
# get all comments for each relevant task
| fp.lmap(lambda task: api.get_comments(task_id=task.id))
# each task's comments are returned as an array, let's flatten this
| fp.flatten()
# dates are returned as strings, let's convert them to datetime objects
| fp.lmap(enrich_date)
# no date filter is applied by default, we don't want all comments
| fp.lfilter(lambda comment: comment["posted_at_date"] > last_synced_date)
# comments do not come with who created the comment by default, we need to hit a separate API to add this to the comment
| fp.lmap(enrich_comment)
# only select the comments posted by our target user
| fp.lfilter(lambda comment: comment["posted_by_user_id"] == filter_user_id)
| fp.sort(key="posted_at_date")
# create a dictionary of task_id => [comments]
| fp.group_by(lambda comment: comment["task_id"])
)
Extras
- to_list
- log
- bp. run
breakpoint()
on the input value - sort
- exactly_one. Throw an error if the input is not exactly one element
- reduce
- pmap. Pass each element of a sequence into a pipe'd function
Coming From Ruby?
- uniq => distinct
- detect =>
where(some="Condition") | first
orwhere_attr(some="Condition") | first
Module Alias
Create a module alias for funcy-pipe
to make things clean (import *
always irks me):
# fp.py
from funcy_pipe import *
# code py
import fp
Inspiration
- Elixir's pipe operator.
array |> map(fn) |> filter(fn)
- Ruby's enumerable library.
array.map(&:fn).filter(&:fn)
- https://pypi.org/project/funcy-chain
- https://github.com/JulienPalard/Pipe
TODO
- tests
- docs for additional utils
- relax python version
- fix typing threading
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for funcy_pipe-0.5.0-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 18f6105bafe65061bf30d3252427126e5c7b5ffbdc115fa19f7e8c21b89e222c |
|
MD5 | 532a63ee30e6bc6a17c97f4e2979a8fb |
|
BLAKE2b-256 | 84df144f2534c9c5f4a7582a2ddc97709d7ce87270561d02a910659267110244 |