Make BZ2File's fileobj support easier to use.

The fileobj argument was added during the 3.3 development cycle, so this change
does not break backward compatibility with 3.2.
diff --git a/Lib/bz2.py b/Lib/bz2.py
index 51b9ac4..ae59407 100644
--- a/Lib/bz2.py
+++ b/Lib/bz2.py
@@ -39,13 +39,12 @@
     returned as bytes, and data to be written should be given as bytes.
     """
 
-    def __init__(self, filename=None, mode="r", buffering=None,
-                 compresslevel=9, *, fileobj=None):
+    def __init__(self, filename, mode="r", buffering=None, compresslevel=9):
         """Open a bzip2-compressed file.
 
-        If filename is given, open the named file. Otherwise, operate on
-        the file object given by fileobj. Exactly one of these two
-        parameters should be provided.
+        If filename is a str or bytes object, is gives the name of the file to
+        be opened. Otherwise, it should be a file object, which will be used to
+        read or write the compressed data.
 
         mode can be 'r' for reading (default), 'w' for (over)writing, or
         'a' for appending.
@@ -91,15 +90,15 @@
         else:
             raise ValueError("Invalid mode: {!r}".format(mode))
 
-        if filename is not None and fileobj is None:
+        if isinstance(filename, (str, bytes)):
             self._fp = open(filename, mode)
             self._closefp = True
             self._mode = mode_code
-        elif fileobj is not None and filename is None:
-            self._fp = fileobj
+        elif hasattr(filename, "read") or hasattr(filename, "write"):
+            self._fp = filename
             self._mode = mode_code
         else:
-            raise ValueError("Must give exactly one of filename and fileobj")
+            raise TypeError("filename must be a str or bytes object, or a file")
 
     def close(self):
         """Flush and close the file.