Repository: imageio/imageio

Issue:
`if imageio.get_reader(...): pass` fails for FfmpegFormat.Reader objects
The following statement:

`if imageio.get_reader('<video0>'): pass`

raises 'OverflowError: cannot convert float infinity to integer' (at least in Python 2.7)

It seems that `FfmpegFormat.Reader` has no `__nonzero__()` method (nor `__bool__()` for Python 3?), so the `__len__()` method is evaluated, which, in this case, returns `float('inf')`.

A quick hack for anyone running into this issue could be to use `if ... is not None`.
(see [stackoverflow](https://stackoverflow.com/a/7816439/4720018))



Discussion:

Patch:
diff --git a/imageio/core/format.py b/imageio/core/format.py
index 34ce741..c5e093a 100644
--- a/imageio/core/format.py
+++ b/imageio/core/format.py
@@ -30,12 +30,22 @@ a format object using ``imageio.formats.add_format()``.
 # imageio.get_reader and imageio.get_writer.
 
 import os
+import sys
 
 import numpy as np
 
 from . import Array, asarray
 
 
+MODENAMES = {
+    "i": "single-image",
+    "I": "multi-image",
+    "v": "single-volume",
+    "V": "multi-volume",
+    "?": "any-mode",
+}
+
+
 class Format(object):
     """ Represents an implementation to read/write a particular file format
     
@@ -153,8 +163,9 @@ class Format(object):
         """
         select_mode = request.mode[1] if request.mode[1] in "iIvV" else ""
         if select_mode not in self.modes:
+            modename = MODENAMES.get(select_mode, select_mode)
             raise RuntimeError(
-                "Format %s cannot read in mode %r" % (self.name, select_mode)
+                "Format %s cannot read in %s mode" % (self.name, modename)
             )
         return self.Reader(self, request)
 
@@ -167,8 +178,9 @@ class Format(object):
         """
         select_mode = request.mode[1] if request.mode[1] in "iIvV" else ""
         if select_mode not in self.modes:
+            modename = MODENAMES.get(select_mode, select_mode)
             raise RuntimeError(
-                "Format %s cannot write in mode %r" % (self.name, select_mode)
+                "Format %s cannot write in %s mode" % (self.name, modename)
             )
         return self.Writer(self, request)
 
@@ -407,7 +419,10 @@ class Format(object):
             return self.iter_data()
 
         def __len__(self):
-            return self.get_length()
+            n = self.get_length()
+            if n == float("inf"):
+                n = sys.maxsize
+            return n
 
         # To implement
 
diff --git a/imageio/core/functions.py b/imageio/core/functions.py
index 71a7366..3a579b0 100644
--- a/imageio/core/functions.py
+++ b/imageio/core/functions.py
@@ -81,6 +81,7 @@ import numpy as np
 
 from . import Request, RETURN_BYTES
 from .. import formats
+from .format import MODENAMES
 
 
 MEMTEST_DEFAULT_MIM = "256MB"
@@ -176,8 +177,9 @@ def get_reader(uri, format=None, mode="?", **kwargs):
     else:
         format = formats.search_read_format(request)
     if format is None:
+        modename = MODENAMES.get(mode, mode)
         raise ValueError(
-            "Could not find a format to read the specified file " "in mode %r" % mode
+            "Could not find a format to read the specified file in %s mode" % modename
         )
 
     # Return its reader object
@@ -220,8 +222,9 @@ def get_writer(uri, format=None, mode="?", **kwargs):
     else:
         format = formats.search_write_format(request)
     if format is None:
+        modename = MODENAMES.get(mode, mode)
         raise ValueError(
-            "Could not find a format to write the specified file " "in mode %r" % mode
+            "Could not find a format to write the specified file in %s mode" % modename
         )
 
     # Return its writer object
diff --git a/imageio/plugins/ffmpeg.py b/imageio/plugins/ffmpeg.py
index ba0d8e0..e0525b3 100644
--- a/imageio/plugins/ffmpeg.py
+++ b/imageio/plugins/ffmpeg.py
@@ -286,6 +286,10 @@ class FfmpegFormat(Format):
             self.request._video = None
             if self.request.filename in ["<video%i>" % i for i in range(10)]:
                 self.request._video = self.request.filename
+            # Specify input framerate?
+            if self.request._video:
+                if "-framerate" not in str(self._arg_input_params):
+                    self._arg_input_params.extend(["-framerate", str(float(fps or 15))])
             # Get local filename
             if self.request._video:
                 index = int(self.request._video[-2])
diff --git a/imageio/plugins/tifffile.py b/imageio/plugins/tifffile.py
index d7e84ed..4bc6392 100644
--- a/imageio/plugins/tifffile.py
+++ b/imageio/plugins/tifffile.py
@@ -316,7 +316,7 @@ class TiffFormat(Format):
                 if key in WRITE_METADATA_KEYS:
                     # Special case of previously read `predictor` int value
                     # 1(=NONE) translation to False expected by TiffWriter.save
-                    if key=="predictor" and not isinstance(value, bool):
+                    if key == "predictor" and not isinstance(value, bool):
                         self._meta[key] = value > 1
                     else:
                         self._meta[key] = value


Test patch:
diff --git a/tests/test_ffmpeg.py b/tests/test_ffmpeg.py
index 51af080..3fecb3a 100644
--- a/tests/test_ffmpeg.py
+++ b/tests/test_ffmpeg.py
@@ -4,6 +4,7 @@
 
 from io import BytesIO
 import os
+import sys
 import gc
 import time
 import threading
@@ -100,6 +101,16 @@ def test_select():
     assert imageio.formats.search_read_format(core.Request(fname1, "rI")) is F
 
 
+def test_integer_reader_length():
+    # Avoid regression for #280
+    r = imageio.get_reader("imageio:cockatoo.mp4")
+    assert r.get_length() == float("inf")
+    assert isinstance(len(r), int)
+    assert len(r) == sys.maxsize
+    assert bool(r)
+    assert True if r else False
+
+
 def test_read_and_write():
 
     R = imageio.read(get_remote_file("images/cockatoo.mp4"), "ffmpeg")