Repository: joke2k/faker

Issue:
faker command line fails with "faker.exceptions.UnsupportedFeature: `image` requires the `Pillow` python library."
* Faker version: 8.8.2
* OS: Ubuntu

It looks like the image faker added in #1254 / 8.5.0 broke the faker command line?

is the fix to catch `UnsupportedFeature` in cli.py, and maybe print a warning?

### Steps to reproduce

1. Install faker in a virtualenv
1. run in the terminal `faker`

### Expected behavior

cli should output fake data

### Actual behavior

Fails with exception:

faker.exceptions.UnsupportedFeature: `image` requires the `Pillow` python library.




Discussion:
> is the fix to catch UnsupportedFeature in cli.py, and maybe print a warning?
 
Yeah, I think that's the right place. Do y u have time to work on a Pull Request?

Resolving patch:
diff --git a/faker/cli.py b/faker/cli.py
--- a/faker/cli.py
+++ b/faker/cli.py
@@ -7,7 +7,7 @@
 from pathlib import Path
 from typing import Any, Dict, List, Optional, TextIO
 
-from faker import VERSION, Faker, documentor
+from faker import VERSION, Faker, documentor, exceptions
 from faker.config import AVAILABLE_LOCALES, DEFAULT_LOCALE, META_PROVIDERS_MODULES
 
 __author__ = 'joke2k'
@@ -86,8 +86,15 @@ def print_doc(provider_or_field=None,
 
     else:
         doc = documentor.Documentor(fake)
+        unsupported = []
 
-        formatters = doc.get_formatters(with_args=True, with_defaults=True)
+        while True:
+            try:
+                formatters = doc.get_formatters(with_args=True, with_defaults=True, excludes=unsupported)
+            except exceptions.UnsupportedFeature as e:
+                unsupported.append(e.name)
+            else:
+                break
 
         for provider, fakers in formatters:
 
@@ -104,7 +111,7 @@ def print_doc(provider_or_field=None,
 
             for p, fs in d.get_formatters(with_args=True, with_defaults=True,
                                           locale=language,
-                                          excludes=base_provider_formatters):
+                                          excludes=base_provider_formatters + unsupported):
                 print_provider(d, p, fs, output=output)
 
 
diff --git a/faker/exceptions.py b/faker/exceptions.py
--- a/faker/exceptions.py
+++ b/faker/exceptions.py
@@ -10,3 +10,6 @@ class UniquenessException(BaseFakerException):
 
 class UnsupportedFeature(BaseFakerException):
     """The requested feature is not available on this system."""
+    def __init__(self, msg, name):
+        self.name = name
+        super().__init__(msg)
diff --git a/faker/providers/misc/__init__.py b/faker/providers/misc/__init__.py
--- a/faker/providers/misc/__init__.py
+++ b/faker/providers/misc/__init__.py
@@ -305,7 +305,7 @@ def image(self, size=(256, 256), image_format='png', hue=None, luminosity=None):
             import PIL.Image
             import PIL.ImageDraw
         except ImportError:
-            raise UnsupportedFeature("`image` requires the `Pillow` python library.")
+            raise UnsupportedFeature("`image` requires the `Pillow` python library.", "image")
 
         (width, height) = size
         image = PIL.Image.new('RGB', size, self.generator.color(hue=hue, luminosity=luminosity))


Test patch:
diff --git a/tests/providers/test_misc.py b/tests/providers/test_misc.py
--- a/tests/providers/test_misc.py
+++ b/tests/providers/test_misc.py
@@ -326,9 +326,11 @@ def test_image(self, faker):
 
     def test_image_no_pillow(self, faker):
         with patch.dict("sys.modules", {"PIL": None}):
-            with pytest.raises(exceptions.UnsupportedFeature):
+            with pytest.raises(exceptions.UnsupportedFeature) as excinfo:
                 faker.image()
 
+            assert excinfo.value.name == "image"
+
     def test_dsv_with_invalid_values(self, faker):
         with pytest.raises(ValueError):
             faker.dsv(num_rows='1')