dwt / fluent Goto Github PK
View Code? Open in Web Editor NEWPython wrapper for stdlib (and other) objects to give them a fluent interface.
License: ISC License
Python wrapper for stdlib (and other) objects to give them a fluent interface.
License: ISC License
Some snippets of code showing how to use this library- beyond the enticing one in the README.md would be sooo helpful.
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?
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?
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.
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?
>>> _('123.456').int()
123.456
@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:
_.each
should behave the same for all the other iterators like .each()
, .filter()
and friends_.each
should behave consistent in all contexts if possible_(dict(foo='bar')).call(_.each['foo'])._ == 'bar'
.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.
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
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)
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.
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... :)
__rmul__
to support 2*_.each
. Similar for other __r...__
functions, see e.g. _(dir(int)).filter(lambda it: it.startswith("__r")).to(list)
._.each
doesn't work as expected, e.g. _(dir(int)).filter(_.each.startswith("__r")).to(list)
doesn't filter anything out. ,$,|
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)
.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.
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...
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.
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)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.