Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not possible to seed uuid4 #484

Closed
J535D165 opened this issue Mar 17, 2017 · 16 comments · Fixed by #1050
Closed

Not possible to seed uuid4 #484

J535D165 opened this issue Mar 17, 2017 · 16 comments · Fixed by #1050

Comments

@J535D165
Copy link
Contributor

It is not possible to seed the uuid4 property.

>>> f1 = Faker()
>>> f1.seed(4321)
>>> print(f1.uuid4())
4a6d35db-b61b-49ed-a225-e16bc164f7cc

>>> f2 = Faker()
>>> f2.seed(4321)
>>> print(f2.uuid4())
b5f05be8-2f57-4a52-9b6f-5bcd03125278

The solution is pretty much given in:
http://stackoverflow.com/questions/41186818/how-to-generate-a-random-uuid-which-is-reproducible-with-a-seed-in-python

@fcurella
Copy link
Collaborator

Thank you for the report, good catch!

Would you mind submit a Pull Request?

@J535D165
Copy link
Contributor Author

The same issue for Faker.binary().

I am working on a unit test for the seeding part. But there is another issue that needs a fix first.

fcurella added a commit that referenced this issue Mar 20, 2017
Make it possible to seed uuid4 property #484
@fcurella
Copy link
Collaborator

Closed in #486

@J535D165 can you open a separate issue for seeding .binary()?

@fcurella fcurella reopened this Mar 20, 2017
@fcurella
Copy link
Collaborator

reopened so I can close it when we have tests

@kevin-brown
Copy link

It was mentioned on Stack Overflow, but the patch doesn't guarantee that the generated UUID is version 4 (which is what uuid4 generates).

@J535D165
Copy link
Contributor Author

@kevin-brown I do agree that this is not a valid uuid4. Nevertheless, the format is UUID (32 alphanumeric characters and four hyphens). So I don't think there is an issue.

@fcurella
Copy link
Collaborator

fcurella commented Mar 20, 2017

@J535D165 @kevin-brown the method is called uuid4, not uuid, so I think users might expect to get a valid uuid4 after all.

That said, I"m still not sure if there is a way that we can fix it, or that we should. If python's uuid4 doesn't return an uuid4 under some conditions, wouldn't this be a bug in Python?

@kevin-brown
Copy link

That said, I"m still not sure if there is a way that we can fix it, or that we should. If python's uuid4 doesn't return an uuid4 under some conditions, wouldn't this be a bug in Python?

It's not that Python's uuid4 doesn't return a UUIDv4 identifier, it's that the pull request which added the ability to seed uuid4 in Faker does not always generate a valid UUIDv4 identifier.

@J535D165
Copy link
Contributor Author

@kevin-brown Do you know how to make it valid?

Is it correct that you can't see a difference between an (incorrect) UUID4 in Faker and a valid UUID4?

@kevin-brown
Copy link

Is it correct that you can't see a difference between an (incorrect) UUID4 in Faker and a valid UUID4?

That is not correct. And 15/16 times it will produce a UUID that is not version 4.

>>> u = uuid.UUID(int=random.getrandbits(128))
>>> u
UUID('7119ccd3-e9be-c160-8d0d-608e5f5ea285')
>>> u.version
12

There are a total of 8 bits that must be set manually in order for it to be properly detected as a UUIDv4.

>>> uuid.UUID(int=(random.getrandbits(128) | (1<<63) | (1<<78)) & (~(1<<79) & ~(1<<77) & ~(1<<76) & ~(1<<62))).version
4
>>> uuid.UUID(int=(random.getrandbits(128) | (1<<63) | (1<<78)) & (~(1<<79) & ~(1<<77) & ~(1<<76) & ~(1<<62))).version
4
>>> uuid.UUID(int=(random.getrandbits(128) | (1<<63) | (1<<78)) & (~(1<<79) & ~(1<<77) & ~(1<<76) & ~(1<<62))).version
4
>>> uuid.UUID(int=(random.getrandbits(128) | (1<<63) | (1<<78)) & (~(1<<79) & ~(1<<77) & ~(1<<76) & ~(1<<62))).version
4
>>> uuid.UUID(int=(random.getrandbits(128) | (1<<63) | (1<<78)) & (~(1<<79) & ~(1<<77) & ~(1<<76) & ~(1<<62))).version
4

@michaelvilensky
Copy link

I think we should revert the pull request to return the original functionality for uuid4 as it currently breaks things.
For seed support another method can be added: uuid or uuid_seed which will implement the pull request logic: str(uuid.UUID(int=random.getrandbits(128)))

@J535D165
Copy link
Contributor Author

Let's revert it or use the version proposed by Kevin.

But can you explain me what breaks?

@kungfoome
Copy link
Contributor

Kevins solution appears to work properly. @kevin-brown can you create a pull request, I don't see any currently to update this.

@MarkJB
Copy link

MarkJB commented Nov 30, 2020

Was this fixed? I'm not able to create deterministic UUIDs with Faker-4.17.1


for _ in range(10):
     random_seed = 1234
     baseline_fake = Faker()
     baseline_fake.seed(random_seed)
     expected_uuids = [baseline_fake.uuid4() for i in range(1000)]
     new_fake = Faker()
     new_fake.seed(random_seed)
     new_uuids = [new_fake.uuid4() for i in range(1000)]
     assert new_uuids == expected_uuids
     
Traceback (most recent call last):
  File "<input>", line 4, in <module>
  File "C:\code\sdk_unit_test\venv\lib\site-packages\faker\proxy.py", line 89, in __getattribute__
    raise TypeError(msg)
TypeError: Calling '.seed()' on instances is deprecated. Use the class method 'Faker.seed()' instead.

from faker import Faker
Faker.seed(123)
my_fake = Faker()
my_second_fake = Faker()
my_fake.uuid4()
'c4da537c-1651-4dae-8486-7db30d67b366'
my_second_fake.uuid4()
'd6a82a95-1b92-4e0a-843c-def36840ff07'

@kevin-brown
Copy link

The tests which were added in #1050 (and closed out this ticket) are still in the repo at

def test_uuid4_seedability(self, faker, num_samples):
for _ in range(num_samples):
random_seed = faker.random_int()
faker.seed_instance(random_seed)
expected_uuids = [faker.uuid4() for _ in range(100)]
faker.seed_instance(random_seed)
new_uuids = [faker.uuid4() for _ in range(100)]
assert new_uuids == expected_uuids

I don't use Faker anymore, but after looking at the code it looks like it should now work with seeding and properly return v4 UUIDs.

@MarkJB
Copy link

MarkJB commented Nov 30, 2020

.seed_instance() was what I was missing.

I followed the link to the commit in #1050 and the tests were using .seed() which was what was thowing me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants