Coder Social home page Coder Social logo

dwt / fluent Goto Github PK

View Code? Open in Web Editor NEW
59.0 3.0 2.0 642 KB

Python wrapper for stdlib (and other) objects to give them a fluent interface.

License: ISC License

Python 100.00%
python-library fluent-interface convenience-methods wrapper python3

fluent's People

Contributors

cromulentbanana avatar dwt avatar gpkc avatar paw-eloquent-safe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

gpkc javadba

fluent's Issues

Automatic fallback to .self on AttributeError

What is the reasoning for not falling back to self automatically if a wrapped function returns None?

for example,

_([1, 5, 2]).append(6).append(3).sort().call(print)._

would be way nicer than

_([1, 5, 2]).append(6).self.append(3).self.sort().self.call(print)._

Could there be a option to enable such a fallback?

How to convert iterable of tuples to dict?

Hey there, i have a fluentpy expression along these lines

a = [1,2,3,4]
b = "abcd"
_(a).zip(b).print()._

This gives me a iterable of 2-tuples. Obviously, i could wrap this in a dict() call, but that is not really fluent.

dict(_(a).zip(b)._)

Is there a fluent way to do this conversion?

Thank you! I needed this fluent interface library you can not believe how much.

Feel free to delete this issue as spam.. I am just so relieved this library exists. I have spent days searching for and trying out alternatives - such as the pipe library (and even contributed to it) and using composition using functools.reduce. This is just way better. Oh - and the lib to import all of python .. man you're a genius.

Typehinting for IDE suggestions.

Hey there,

i love the idea of this library. One issue though: there are no IDE autocomplete suggestions when using this.

I managed to get rudimentary suggestions to work by changing wrap to this:

WrappedT = typing.TypeVar('WrappedT')

def wrap(wrapped: WrappedT, *, previous=None) -> WrappedT:

sadly, this means i have to from fluentpy.wrapper import wrap as _ since type checkers dont understand the concept of a callable module, at least not the way you've done it. on the upside, i get autocomplete suggestions!

Would it be possible to add this to the library, maybe a bit more extensive to be able to see the Wrapper methods like .each? Maybe there's even a way to get it to work with the direct module import?

Automatic unwrapping of _.each

@kbauer: I'd like to discuss auto unwrapping seperately - your input is very welcome.

Regarding the auto conversion in map(): I am also constantly annoyed by this, but I am also extremely reluctant to change this, mainly for these reasons:

  1. _.each should behave the same for all the other iterators like .each(), .filter() and friends
  2. _.each should behave consistent in all contexts if possible
_(dict(foo='bar')).call(_.each['foo'])._ == 'bar'
  1. It should be possible to abstract over _.each with .map() and friends. Like this:
_(['foo', 'bar', 'baz']).map(_.each).map(lambda each: each._).map(_.each(print)._)

Now that I think about it, it is really hard to come up with a useful example, where one would want to abstract over _.each with the iterators. Maybe it would be good enough to have an off switch for auto termination that one would have to explicitly set on _.each. Maybe something like _.each._disable_auto_termination() (now that is ugly, but also unlikely to clash with any operation you want to do on _.each)

I am really not sure. I know that it is impossible to really fix _.each auto termination in all circumstances, as you can always wrap in a dict or something to make it invisible to wrapper().

But maybe 'most of the time' is actually good enough to make a difference?

As for a migration, we could start by adding a warning to all wrappers if you hand in a unterminated _.each and ask users to report if they see it. That way we get a feel if there is actual usage of this feature.

Possible solution to "call()"

Howdy,

Thanks for a great library. For various reasons, I decided to write my own version of it, but it was heavily influenced by your work.

In my version, I was able to fix the "call()" issue you mention in your readme. Specifically, if I want to call the method foo on each element in my iterable, I can do
from_(myit).map(each.foo())
rather than
from_(myit).map(each.foo.call)

For example, here, I can get the backing numpy array from every axes in a figure and concatenate them:

from_(plt.gcf().axes)\
    .map(each.images[0].get_data())\
    .map(each.reshape(1,512,512))\
    .to(np.vstack)

My code is attached. Hope this helps!
fluentutil.py.txt

Better subprocess integration

pipe Will try, but it took me days just to answer to your comments :/ For now I am just attaching my experient (pipe.py.txt).

Regarding sh: It looks quite interesting, and most of my scripting is Unix anyway (or WSL if on Windows). It is however somewhat inconvenient to use with fluentpy.

_(range(10)).map(lambda it: str(it)+"\n").call(lambda it: sh.sed("s/^/>> /", _in=it)).to(list)
                                                      ^^                         ^^

In scripting contexts, something like

_(strings).sh.sed("s/^/>> /").to(list)

would be preferable. As it is, that would make sh a thing wrapper to the sh module, that sets _in. And maybe for consistency some ish, that also sets _iter=True...

The downside would be, that it would introduce a feature that doesn't work on Windows. My popen based experiment is platform independent by contrast. Will look into it more.

Originally posted by @kbauer in #6 (comment)

New release?

Last official release was twelve months back - and you have done quite a bit of work since then. While I can git clone and install locally it would be helpful to have a pip install able for distributions.

New Features on _.each

Ah, all clear regarding the missing comment. But yes, I would like to add as many overloads as are possible with _.each - so keep coming back if you find something that can be implemented.

With some delay... :)

_.each

  • __rmul__ to support 2*_.each. Similar for other __r...__ functions, see e.g. _(dir(int)).filter(lambda it: it.startswith("__r")).to(list).
  • Invoking methods on _.each doesn't work as expected, e.g. _(dir(int)).filter(_.each.startswith("__r")).to(list) doesn't filter anything out.
  • The ,$,| operators could be overloaded as eager boolean operators (like numpy does). Though precedence rules are an issue, it would allow writing _(range(10)).filter( (_.each > 3) & (_.each < 7) ).to(list).

Prefices

Regarding the prefixes: I really don't know what the best way here would be. I kind of like that the default case is not lazy and I find the I prefix intuitive (though python2-ish). At the same time I haven't found a good prefix for a non lazy variant.

That being said - I tried at least to be internally consistent, but am of course open to suggestions.

"Iterator by default" can be annoying for debugging, since lazy evaluation often doesn't produce useful stack traces.
"Iterator by default" can be annoying for debugging, because it delays the failure. In

import fluentpy as _

def fail(value):
    assert False, "fail"

items = _(range(10)).imap(fail)

for item in items:
    print(item)

the line where items is defined doesn't appear in the backtrace while with map it would. So, for my personal use-cases your current choice almost always will be preferable actually.

On the other hand, making eager evaluation the default means that code written with fluentpy will be brittle. The original purpose of a function might work well with _(...).filter, but will suddenly fail if the passed iterable is large or infinite.

Documentation (1)

It could be useful to point out, that the wrappers can be used as decorators to side-step the limited features of lambdas. E.g.

items = _(range(5))
@items.call
def items(its):
    for it in its:
        yield it
        yield it
print(items.to(list))

This would be yet another advantage of the suffix notation for filtering effects...

Documentation (2)

Ad-hoc, I thought it might be useful to provide custom extensions, e.g. let's say implementing a .groupby that groups non-consecutive elements. Until I realized, that this is covered by .call. It might be worth pointing this out explicitly.

Subprocess utility

A wrapper around subprocess.Popen would be useful, that allows to do something like

lines = _(["hello","world"]).pipe(["sed", "s/l/x/g"]).to(list)

It can be done with .call and a function wrapping around subprocess.Popen; In order to prevent deadlocks, it requires multiple threads though; I had some success building a function that allowed _(...).call(pipe(...)).... by having a thread feed the input iterator to the Popen.stdin and returning an iterator over Popen.stdout.

Originally posted by @kbauer in #5 (comment)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.