Integration with other libraries

Integration of other libraries or just your own custom functions, typically involves .call().

Lets take the shell integration library sh as an example. This library adds a function like interface to shell callouts like this: ifconfig(), sed('s/^/>> /', _in='foo\nbar\baz'). This is problematic, as function call chains want callables, that get one input argument - in our case stdin, or the _in parameter. To support this library, you can manually curry what you need, or create a small adapter object, that does this currying:

#!/usr/bin/env python

import typing
import sh

import fluentpy as _

class SHWrapper(object):
    def __getattr__(self, command):
        
        def _prepare_stdin(stdin):
            if isinstance(stdin, (typing.Text, sh.RunningCommand)):
                return stdin  # use immediately
            elif isinstance(stdin, typing.Iterable):
                return _(stdin).map(str).join('\n')._
            else:
                return str(stdin)  # just assume the caller wants to process it as string
        
        def command_wrapper(*args, **kwargs):
            def command_with_arguments_wrapper(stdin):
                return getattr(sh, command)(*args, **kwargs, _in=_prepare_stdin(stdin))
            return command_with_arguments_wrapper
        
        return command_wrapper

pipe = SHWrapper()

_(range(10)).call(pipe.sed('s/^/>> /')).call(pipe.sort('-r')).print()

This library is wrapped in the SHWrapperobject, that a) adapting the way stdin is handled, to adapt various input types to serve as stdin, as well as b) adapt the interface to create simple callables in two steps via currying, instead of requiring stdin in the same call that defines the arguments.

With that .call() can be used, to insert sh callouts in call chains:

_(range(10)).call(pipe.sed('s/^/>> /')).call(pipe.sort('-r')).print()

So to summarize: If you want to adapt your own libraries to serve inside of call chains:

  • If the interface is allready plain callables, you are in luck, just use them.

  • If not, you might need to adapt the interface of the library to single input functions.