Repository: joke2k/faker

Issue:
`.prefix`/`.suffix` returns a tuple instead of a single value
`.prefix` (and `.suffix`) can occasionally return a tuple of values instead of a single value when `prefixes_male` and `prefixes_female` (or `suffixes_*`) are present in the provider.

[See here for the code responsible.](https://github.com/joke2k/faker/blob/2af330e09d84306d10921fed00ad2e5cc8e3d36f/faker/providers/person/__init__.py#L93-L94)

I wasn't sure if this was intentional (it's documented to do so -- then again, the documentation is autogenerated, isn't it?), so I didn't make a PR yet, but it's certainly counterintuitive.



Discussion:
Hi @akx, thanks for your report.

I believe it is a bug, but I'd like @joke2k to confirm that returning a tuple is not intended behavior

Definitely a bug, in version 0.4.x it was returning a string and now in version 0.5.x it is returning a tuple, this is breaking our scripts... can u fix pls?
see:
from faker import Factory
fakeDataGenerator = Factory.create("en-US")
fakeDataGenerator.prefix()
(u'Mrs.', u'Ms.', u'Miss', u'Dr.')
fakeDataGenerator.prefix()
(u'Mr.', u'Dr.')

temporary fix:
fakeDataGenerator.prefix()[0] if isinstance(fakeDataGenerator.prefix(), tuple) else fakeDataGenerator.prefix()

@akx can you submit a PR?


Resolving patch:
diff --git a/faker/providers/person/__init__.py b/faker/providers/person/__init__.py
--- a/faker/providers/person/__init__.py
+++ b/faker/providers/person/__init__.py
@@ -71,7 +71,8 @@ def prefix(cls):
         if hasattr(cls, 'prefixes'):
             return cls.random_element(cls.prefixes)
         if hasattr(cls, 'prefixes_male') and hasattr(cls, 'prefixes_female'):
-            return cls.random_element((cls.prefixes_male, cls.prefixes_female))
+            prefixes = cls.random_element((cls.prefixes_male, cls.prefixes_female))
+            return cls.random_element(prefixes)
         return ''
 
     @classmethod
@@ -91,7 +92,8 @@ def suffix(cls):
         if hasattr(cls, 'suffixes'):
             return cls.random_element(cls.suffixes)
         if hasattr(cls, 'suffixes_male') and hasattr(cls, 'suffixes_female'):
-            return cls.random_element((cls.suffixes_male, cls.suffixes_female))
+            suffixes = cls.random_element((cls.suffixes_male, cls.suffixes_female))
+            return cls.random_element(suffixes)
         return ''
 
     @classmethod


Test patch:
diff --git a/faker/tests/__init__.py b/faker/tests/__init__.py
--- a/faker/tests/__init__.py
+++ b/faker/tests/__init__.py
@@ -6,10 +6,21 @@
 import os
 import random
 import unittest
+import sys
 
-from faker import Generator
+try:
+    from StringIO import StringIO
+except ImportError:
+    from io import StringIO
+
+from faker import Generator, Factory
 from faker.utils import text, decorators
 
+try:
+    string_types = (basestring,)
+except NameError:
+    string_types = (str,)
+
 
 TEST_DIR = os.path.dirname(__file__)
 
@@ -153,16 +164,25 @@ def test_magic_call_calls_format_with_arguments(self):
 
     def test_documentor(self):
         from faker.cli import print_doc
-        print_doc()
-        print_doc('address')
-        print_doc('faker.providers.it_IT.person')
+        output = StringIO()
+        print_doc(output=output)
+        print_doc('address', output=output)
+        print_doc('faker.providers.it_IT.person', output=output)
+        assert output.getvalue()
         self.assertRaises(AttributeError,
                           self.generator.get_formatter,
                           'barFormatter')
 
     def test_command(self):
-        from faker.cli import execute_from_command_line
-        execute_from_command_line(['faker', 'address'])
+        from faker.cli import Command
+        orig_stdout = sys.stdout
+        try:
+            sys.stdout = StringIO()
+            command = Command(['faker', 'address'])
+            command.execute()
+            assert sys.stdout.getvalue()
+        finally:
+            sys.stdout = orig_stdout
 
     def test_slugify(self):
         slug = text.slugify("a'b/c")
@@ -231,6 +251,14 @@ def test_datetime_safe(self):
         result = datetime_safe.date(2008, 2, 29).strftime('%y')
         self.assertEqual(result, r'08')
 
+    def test_prefix_suffix_always_string(self):
+        # Locales known to contain `*_male` and `*_female`.
+        for locale in ("bg_BG", "dk_DK", "en", "ru_RU", "tr_TR"):
+            f = Factory.create(locale=locale)
+            for x in range(20):  # Probabilistic testing.
+                assert isinstance(f.prefix(), string_types)
+                assert isinstance(f.suffix(), string_types)
+
 
 if __name__ == '__main__':
     unittest.main()