Repository: joke2k/faker

Issue:
uuid4 should return UUID instead of str
__Context__: I'm using faker in combination with [FactoryBoy](https://github.com/FactoryBoy/factory_boy) to test [Django](https://www.djangoproject.com/) models. I have this test to make sure some data dict generated from model data is JSON-serializable. The test passed, but not the code in production. (`Object of type UUID is not JSON serializable`).

Now, of course the fix to the offending code is simple:

``` diff
- data['uuid'] = model.uuid
+ data['uuid'] = str(model.uuid)
```

but the problem is two-fold:

1. __The fact that `uuid4` returns `str` is confusing__. I didn't pay attention and couldn't test properly.
2. __There is no provider for actual `UUID` objects__. I can understand if some people want strings that are in fact uuid representations, after all that's [how AutoFixture generates strings](https://github.com/AutoFixture/AutoFixture/wiki/Cheat-Sheet#completely-autogenerated-string) (Autofixture does approximately the same job as faker, but for C#). But there should be a provider for true `UUID`s as well.

### Steps to reproduce

1. Call `fake.uuid4()`

### Expected behavior

`fake.uuid4()` should return an `UUID` object

### Actual behavior

`fake.uuid4()` returns a `str`



Discussion:
we could add an argument to `uuid4()`, like `faker.uuid(coerce=True)`. I'd like to keep the ddefault behavior to a string, for backward compatibility reasons
> I'd like to keep the default behavior to a string, for backward compatibility reasons

Yeah, I figured you'd say that.

An argument to `uuid4` is fine by me. I might even implement it myself.

Resolving patch:
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
@@ -130,12 +130,14 @@ def locale(self):
     def language_code(self):
         return self.random_element(Provider.language_locale_codes.keys())
 
-    def uuid4(self):
+    def uuid4(self, cast_to=str):
         """
         Generates a random UUID4 string.
+        :param cast_to: Specify what type the UUID should be cast to. Default is `str`
+        :type cast_to: callable
         """
         # Based on http://stackoverflow.com/q/41186818
-        return str(uuid.UUID(int=self.generator.random.getrandbits(128)))
+        return cast_to(uuid.UUID(int=self.generator.random.getrandbits(128), version=4))
 
     def password(
             self,


Test patch:
diff --git a/tests/providers/test_misc.py b/tests/providers/test_misc.py
new file mode 100644
--- /dev/null
+++ b/tests/providers/test_misc.py
@@ -0,0 +1,26 @@
+import unittest
+import uuid
+import six
+
+from faker import Faker
+
+
+class TestMisc(unittest.TestCase):
+    """Tests miscellaneous generators"""
+    def setUp(self):
+        self.factory = Faker()
+
+    def test_uuid4(self):
+        uuid4 = self.factory.uuid4()
+        assert uuid4
+        assert isinstance(uuid4, six.string_types)
+
+    def test_uuid4_int(self):
+        uuid4 = self.factory.uuid4(cast_to=int)
+        assert uuid4
+        assert isinstance(uuid4, six.integer_types)
+
+    def test_uuid4_uuid_object(self):
+        uuid4 = self.factory.uuid4(cast_to=lambda x: x)
+        assert uuid4
+        assert isinstance(uuid4, uuid.UUID)