# Buggy code
def file_smart_open(fname, mode="rb", encoding=None):
    """
    Stream from/to local filesystem, transparently (de)compressing gzip and bz2
    files if necessary.

    :arg str fname: The path to the file to open.
    :arg str mode: The mode in which to open the file.
    :arg str encoding: The text encoding to use.
    :returns: A file object
    """
    #
    # This is how we get from the filename to the end result.
    # Decompression is optional, but it always accepts bytes and returns bytes.
    # Decoding is also optional, accepts bytes and returns text.
    # The diagram below is for reading, for writing, the flow is from right to
    # left, but the code is identical.
    #
    #           open as binary         decompress?          decode?
    # filename ---------------> bytes -------------> bytes ---------> text
    #                          raw_fobj        decompressed_fobj   decoded_fobj
    #
    try:  # TODO need to fix this place (for cases with r+ and so on)
        raw_mode = {"r": "rb", "w": "wb", "a": "ab"}[mode]
    except KeyError:
        raw_mode = mode
    raw_fobj = open(fname, raw_mode)
    decompressed_fobj = compression_wrapper(raw_fobj, fname, raw_mode)
    decoded_fobj = encoding_wrapper(decompressed_fobj, mode, encoding=encoding)
    return decoded_fobj


# Traceback (TypeError)
(smartopen)sergeyich:issue152 misha$ git rev-parse --short HEAD
d10166c
(smartopen)sergeyich:issue152 misha$ time python reproduce.py s3://commoncrawl/crawl-002/2010/09/25/0/1285411480200_0.arc.gz
0it [00:00, ?it/s]Traceback (most recent call last):
File "reproduce.py", line 5, in <module>
for i, _ in enumerate(tqdm(smart_open(sys.argv[1], 'rb'))):
File "/Users/misha/envs/smartopen/lib/python3.6/site-packages/tqdm/_tqdm.py", line 953, in __iter__
for obj in iterable:
TypeError: 'closing' object is not iterable


real    0m3.131s
user    0m0.906s
sys     0m0.151s

# Fixed code
def file_smart_open(fname, mode="rb", encoding=None, errors=DEFAULT_ERRORS):
    """
    Stream from/to local filesystem, transparently (de)compressing gzip and bz2
    files if necessary.

    :arg str fname: The path to the file to open.
    :arg str mode: The mode in which to open the file.
    :arg str encoding: The text encoding to use.
    :arg str errors: The method to use when handling encoding/decoding errors.
    :returns: A file object
    """
    #
    # This is how we get from the filename to the end result.
    # Decompression is optional, but it always accepts bytes and returns bytes.
    # Decoding is also optional, accepts bytes and returns text.
    # The diagram below is for reading, for writing, the flow is from right to
    # left, but the code is identical.
    #
    #           open as binary         decompress?          decode?
    # filename ---------------> bytes -------------> bytes ---------> text
    #                          raw_fobj        decompressed_fobj   decoded_fobj
    #
    try:  # TODO need to fix this place (for cases with r+ and so on)
        raw_mode = {"r": "rb", "w": "wb", "a": "ab"}[mode]
    except KeyError:
        raw_mode = mode
    raw_fobj = open(fname, raw_mode)
    decompressed_fobj = compression_wrapper(raw_fobj, fname, raw_mode)
    decoded_fobj = encoding_wrapper(
        decompressed_fobj, mode, encoding=encoding, errors=errors
    )
    return decoded_fobj