JulienPalard / Pipe

A Python library to use infix notation in Python
MIT License
1.96k stars 113 forks source link

Add path function #55

Closed sergiors closed 4 years ago

sergiors commented 4 years ago

I have been working in a called pyf and used in production.

As asked in issue #38, there a function that I think be useful for everyone that use Pipe project.

Here is a real example where I have been used:

docs = await es.search(index=index_name, body=s.to_dict())
docs = tuple(docs | path(['hits', 'hits'])
                  | map(itemgetter('_source')))
JulienPalard commented 4 years ago

Is it different than:

docs = await es.search(index=index_name, body=s.to_dict())
docs = tuple(docs["hits"]["hits"] | map(itemgetter('_source')))

?

A pipe should represent a flow of data, not a single action.

sergiors commented 4 years ago

If docs["hits"]["hits"] does exist, an exception should be raise, with path I can set a default value, that way, map will not broke and I can get an empty tuple

JulienPalard commented 4 years ago

The pipe library unique goal is to handle stream of data (first paramter should be iterable), not to apply transformations on single objects, so I won't be able to merge this as is.

I mean, it would be ok if it worked like this:

>>> data = [{"a": 1}, {"a": 2}, {"a": 3}, {"a": 4}, {"a": 5}]
>>> list(data | path("a"))
[1, 2, 3, 4, 5]

in which case it could even use glom as a backend, like (not tested):

@Pipe
def path(iterable, path, default=None):
    for item in iterable:
        yield glom(item, path, default)

(But if you don't need this specitif implementation of path, please don't PR it, I'd prefer to accept only code that actually help at least one person.)

If you want a short way to write:

docs.get("hits", {}).get("hits", {})

you should try glom:

glom(docs, "hits.hits", default={})

Please note that I greatly appreciate the time you've spent implementing it, opening a PR to contribute back, thanks for this and sorry to refuse your contribution.

While I'm here, you're (obviously!) still free to use your implementation in your code. In a way pipe could just implement the Pipe decorator, and let users implement all needed functions with it, the provided collection of functions is here as a demo of what's possible, and because I once though they could be usefull to someone, but don't think it's illegitimate to use @Pipe only because I use it internally.

sergiors commented 4 years ago

I got the point. I thought that @Pipe could be used like Ramda, but no problem, your explanation makes sense and try to use glom is a brilliant ideia.

Thanks for the lesson, I learned a little more about python in this issue.