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

Fix #1643 : Fully qualified model name + Unique ShortID generation for DTO Model to avoid collision issues. #1649

Merged
merged 15 commits into from May 13, 2023

Conversation

v3ss0n
Copy link
Contributor

@v3ss0n v3ss0n commented May 10, 2023

Pull Request Checklist

  • New code has 100% test coverage
  • (If applicable) The prose documentation has been updated to reflect the changes introduced by this PR
  • (If applicable) The reference documentation has been updated to reflect the changes introduced by this PR

Description

Bug fix for #1643 - where it cause duplicated DTOModel names collision. Attempted to fixed by adding a 12 char unique id to fully qualified name of model.

This PR adds two new test cases to ensure that the generated model names and schema names are unique

  • First test case to ensure that the model names generated by the backend are unique to avoid naming collisions between different parts of the code.
  • Also next text case check that there are exactly two unique schemas. and that all schema names start with the modle name

Close Issue(s)

Fixes #1643

@v3ss0n v3ss0n requested a review from a team as a code owner May 10, 2023 14:06
@v3ss0n v3ss0n changed the title Fqn random dtoid Fully Qualified Name + Unique ShortID generation for DTO Model to avoid collision issues. May 10, 2023
@v3ss0n v3ss0n changed the title Fully Qualified Name + Unique ShortID generation for DTO Model to avoid collision issues. Fix #1643 : FullyQualifiedName + Unique ShortID generation for DTO Model to avoid collision issues. May 10, 2023
Copy link
Contributor

@peterschutt peterschutt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @v3ss0n - thanks for taking this one on!

When we were talking in discord, I was only referring to the msgspec backend type, however there is also the pydantic backend, so perhaps we can create a utility method on AbstractDTOBackend that accepts unique_name as an argument and returns that with the short uid appended to it. We can then call that method from within create_transfer_model_type on either backend implementation.

Also, tests please:)

Thanks again!

@v3ss0n
Copy link
Contributor Author

v3ss0n commented May 11, 2023

Thanks , i am happy to help. i saw other back-end uses it , i was about to ask tha
Edited : added in AbstractDTOBackend , it works.

Should i write test to see if the method is generating unique ids?

@v3ss0n
Copy link
Contributor Author

v3ss0n commented May 11, 2023

@pytest.mark.parametrize("backend_type", [MsgspecDTOBackend, PydanticDTOBackend])
def test_backend_model_name_uniqueness(backend_type: type[AbstractDTOBackend], backend_context: BackendContext) -> None:
    backend = backend_type(backend_context)
    unique_names: set = set()
    fd: FieldDefinitionsType = FieldDefinition(
        name="a",
        default=Empty,
        parsed_type=ParsedType(int),
        default_factory=None,
        dto_field=None,
        unique_model_name="some_module.SomeModel",
    )
    for i in range(100):
        model_class = backend.create_transfer_model_type("some_module.SomeModel", fd)
        model_name = model_class.unique_name
        assert model_name not in unique_names
        unique_names.add(model_name)

I am trying like this , i don't know how to get unique_name back from the transfer_model .

@peterschutt
Copy link
Contributor

@pytest.mark.parametrize("backend_type", [MsgspecDTOBackend, PydanticDTOBackend])
def test_backend_model_name_uniqueness(backend_type: type[AbstractDTOBackend], backend_context: BackendContext) -> None:
    backend = backend_type(backend_context)
    unique_names: set = set()
    fd: FieldDefinitionsType = FieldDefinition(
        name="a",
        default=Empty,
        parsed_type=ParsedType(int),
        default_factory=None,
        dto_field=None,
        unique_model_name="some_module.SomeModel",
    )
    for i in range(100):
        model_class = backend.create_transfer_model_type("some_module.SomeModel", fd)
        model_name = model_class.unique_name
        assert model_name not in unique_names
        unique_names.add(model_name)

I am trying like this , i don't know how to get unique_name back from the transfer_model .

does model_class.__name__ work?

@v3ss0n
Copy link
Contributor Author

v3ss0n commented May 12, 2023

sync with main , resolved conflict at poetry.lock , its ready for review.

Copy link
Contributor

@peterschutt peterschutt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost there, just need to get that test passing.

tests/dto/factory/test_integration.py Outdated Show resolved Hide resolved
@v3ss0n v3ss0n changed the title Fix #1643 : FullyQualifiedName + Unique ShortID generation for DTO Model to avoid collision issues. Fix #1643 : Fully qualified model name + Unique ShortID generation for DTO Model to avoid collision issues. May 13, 2023
@peterschutt
Copy link
Contributor

Just tested this on the example app - the first 9 characters of each of those random strings is identical across all of the models which I think is due to the first part of uuid1 being a timestamp. This is why you needed to increase the size of the random string in 8e025cb - because the first chars of a timestamp are too slow-moving to be reliably different.

I think we'd be better of just using something like base64.urlsafe_b64encode(os.urandom(6)) for the random component.

Sorry I didn't pick this up earlier!

@provinzkraut
Copy link
Member

I think we'd be better of just using something like base64.urlsafe_b64encode(os.urandom(6))

Why not just use secrets.token_urlsafe(6) for this?

@peterschutt
Copy link
Contributor

I think we'd be better of just using something like base64.urlsafe_b64encode(os.urandom(6))

Why not just use secrets.token_urlsafe(6) for this?

Perfect.

@v3ss0n
Copy link
Contributor Author

v3ss0n commented May 13, 2023

Just tested this on the example app - the first 9 characters of each of those random strings is identical across all of the models which I think is due to the first part of uuid1 being a timestamp. This is why you needed to increase the size of the random string in 8e025cb - because the first chars of a timestamp are too slow-moving to be reliably different.

I think we'd be better of just using something like base64.urlsafe_b64encode(os.urandom(6)) for the random component.

Sorry I didn't pick this up earlier!

I was thinking that too , with uuid1 looks like we need whole of it. it is base off on timestamp so the first chars are not much moving within a few minutes.
I am gonna test with secrets.token_urlsafe(6)

@v3ss0n
Copy link
Contributor Author

v3ss0n commented May 13, 2023

secrets.token_urlsafe() have dashes and undercores , should thate be ok?
results like : dI7YzibZwVA0racC-wh_LPg52Ht3G2qHpooc1QlpTME

@provinzkraut
Copy link
Member

secrets.token_urlsafe(6) have dashes and undercores , should thate be ok?

Probably better not to. Try secrets.token_hex. That's just letters and numbers.

@v3ss0n
Copy link
Contributor Author

v3ss0n commented May 13, 2023

secrets.token_urlsafe(6) have dashes and undercores , should thate be ok?

Probably better not to. Try secrets.token_hex. That's just letters and numbers.

thanks , this look better , going to raise to 8 chars to increase randomness.

In [30]: secrets.token_hex(8)
Out[30]: '342e6bed9da5e8a5'

@v3ss0n
Copy link
Contributor Author

v3ss0n commented May 13, 2023

changed to : secrets.token_hex(8) , tested by incresing loop to 100k , passed locally.

@peterschutt
Copy link
Contributor

@all-contributors add @v3ss0n for code!

@allcontributors
Copy link
Contributor

@peterschutt

I've put up a pull request to add @v3ss0n! 🎉

@v3ss0n
Copy link
Contributor Author

v3ss0n commented May 13, 2023

Thanks a lot!!

@peterschutt peterschutt merged commit 83ffc31 into litestar-org:main May 13, 2023
11 checks passed
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 this pull request may close these issues.

Bug: 500: Two different schemas with the title app.domain.authors.Author have been defined.
3 participants