How to use yaml.load_all with fileinput.input?
Question: Without resorting to `''.join`, is there a Pythonic way to use PyYAML's
`yaml.load_all` with `fileinput.input()` for easy streaming of multiple
documents from multiple sources?

I'm looking for something like the following (non-working example):

    
    
    # example.py
    import fileinput
    
    import yaml
    
    for doc in yaml.load_all(fileinput.input()):
        print(doc)
    

Expected output:

    
    
    $ cat >pre.yaml <<<'--- prefix-doc'
    $ cat >post.yaml <<<'--- postfix-doc'
    $ python example.py pre.yaml - post.yaml <<<'--- hello'
    prefix-doc
    hello
    postfix-doc
    

Of course, `yaml.load_all` expects either a string, bytes, or a file-like
object and `fileinput.input()` is none of those things, so the above example
does not work.

Actual output:

    
    
    $ python example.py pre.yaml - post.yaml <<<'--- hello'
    ...
    AttributeError: FileInput instance has no attribute 'read'
    

You can make the example work with `''.join`, but that's cheating. I'm looking
for a way that does not read the entire stream into memory at once.

We might rephrase the question as _Is there some way to emulate a string,
bytes, or file-like object that proxies to an underlying iterator of strings?_
However, I doubt that `yaml.load_all` actually needs the entire file-like
interface, so that phrasing would ask for more than is strictly necessary.

Ideally I'm looking for the minimal adapter that would support something like
this:

    
    
    for doc in yaml.load_all(minimal_adapter(fileinput.input())):
        print(doc)
    


Answer: The problem with `fileinput.input` is that the resulting object doesn't have a
`read` method, which is what `yaml.load_all` is looking for. If you're willing
to give up `fileinput`, you can just write your own class that will do what
you want:

    
    
    import sys                                                                      
    import yaml                                                                     
    
    class BunchOFiles (object):                                                     
        def __init__(self, *files):                                                 
            self.files = files                                                      
            self.fditer = self._fditer()                                            
            self.fd = self.fditer.next()                                            
    
        def _fditer(self):                                                          
            for fn in self.files:                                                   
                with sys.stdin if fn == '-' else open(fn, 'r') as fd:               
                    yield fd                                                        
    
        def read(self, size=-1):                                                    
            while True:                                                             
                data = self.fd.read(size)                                           
    
                if data:                                                            
                    break                                                           
                else:                                                               
                    try:                                                            
                        self.fd = self.fditer.next()                                
                    except StopIteration:                                           
                        self.fd = None                                              
                        break                                                       
    
            return data                                                             
    
    bunch = BunchOFiles(*sys.argv[1:])                                              
    for doc in yaml.load_all(bunch):                                                
        print doc                                                                   
    

The `BunchOFiles` class gets you an object with a `read` method that will
happily iterate over a list of files until everything is exhausted. Given the
above code and your sample input, we get exactly the output you're looking
for.

