From 7f9820fe153b1a1ad0fe505cf04da2add819f538 Mon Sep 17 00:00:00 2001 From: Marcelo Lino Date: Mon, 2 May 2022 19:16:58 -0300 Subject: [PATCH 01/11] Add UUID_FORMAT config --- django_guid/config.py | 12 +++++++++--- django_guid/utils.py | 10 ++++++++-- docs/settings.rst | 13 ++++++++++++- tests/unit/test_config.py | 13 +++++++++++-- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/django_guid/config.py b/django_guid/config.py index a06a479..0659c1d 100644 --- a/django_guid/config.py +++ b/django_guid/config.py @@ -58,7 +58,11 @@ def integration_settings(self) -> IntegrationSettings: @property def uuid_length(self) -> int: - return self.settings.get('UUID_LENGTH', 32) + return self.settings.get('UUID_LENGTH', 36) + + @property + def uuid_format(self) -> str: + return self.settings.get('UUID_FORMAT', 'hex') def validate(self) -> None: if not isinstance(self.validate_guid, bool): @@ -75,8 +79,10 @@ def validate(self) -> None: raise ImproperlyConfigured('IGNORE_URLS must be an array') if not all(isinstance(url, str) for url in self.settings.get('IGNORE_URLS', [])): raise ImproperlyConfigured('IGNORE_URLS must be an array of strings') - if type(self.uuid_length) is not int or not 1 <= self.uuid_length <= 32: - raise ImproperlyConfigured('UUID_LENGTH must be an integer and be between 1-32') + if type(self.uuid_length) is not int or not 1 <= self.uuid_length <= 36: + raise ImproperlyConfigured('UUID_LENGTH must be an integer and be between 1-36') + if self.uuid_format not in ('hex', 'string', 'int'): + raise ImproperlyConfigured('UUID_FORMAT must be either hex, int, or string') self._validate_and_setup_integrations() diff --git a/django_guid/utils.py b/django_guid/utils.py index bb362de..3105eda 100644 --- a/django_guid/utils.py +++ b/django_guid/utils.py @@ -70,9 +70,15 @@ def generate_guid(uuid_length: Optional[int] = None) -> str: :return: GUID """ + guid = uuid.uuid4() + if settings.uuid_format == 'string': + guid = str(guid) + else: + guid = str(getattr(guid, settings.uuid_format)) + if uuid_length is None: - return uuid.uuid4().hex[: settings.uuid_length] - return uuid.uuid4().hex[:uuid_length] + return guid[: settings.uuid_length] + return guid[:uuid_length] def validate_guid(original_guid: str) -> bool: diff --git a/docs/settings.rst b/docs/settings.rst index 94120e1..1026bff 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -14,6 +14,7 @@ Default settings are shown below: 'EXPOSE_HEADER': True, 'INTEGRATIONS': [], 'UUID_LENGTH': 32, + 'UUID_FORMAT': 'hex', } @@ -75,9 +76,19 @@ URL endpoints where the middleware will be disabled. You can put your health che UUID_LENGTH ----------- -* **Default**: ``32`` +* **Default**: ``36`` * **Type**: ``int`` If a full UUID hex is too long for you, this settings lets you specify the length you wish to use. The chance of collision in a UUID is so low, that most systems will get away with a lot fewer than 32 characters. + +UUID_LENGTH +----------- +* **Default**: ``hex`` +* **Type**: ``string`` + +If a UUID hex is not suitable for you, this settings lets you specify the format you wish to use. The options are: +* ``hex``: The default, a 32 character hexadecimal string. +* ``int``: A 128 bit integer. +* ``str``: A 36 character string. \ No newline at end of file diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py index c7b1dd0..028275c 100644 --- a/tests/unit/test_config.py +++ b/tests/unit/test_config.py @@ -87,14 +87,23 @@ def test_not_string_in_igore_urls(): def test_uuid_len_fail(): - for setting in [True, False, {}, [], 'asd', -1, 0, 33]: + for setting in [True, False, {}, [], 'asd', -1, 0, 37]: mocked_settings = deepcopy(django_settings.DJANGO_GUID) mocked_settings['UUID_LENGTH'] = setting with override_settings(DJANGO_GUID=mocked_settings): - with pytest.raises(ImproperlyConfigured, match='UUID_LENGTH must be an integer and be between 1-32'): + with pytest.raises(ImproperlyConfigured, match='UUID_LENGTH must be an integer and be between 1-36'): Settings().validate() +@pytest.mark.parametrize('uuid_format', ['bytes', 'urn', 'bytes_le']) +def test_uuid_format_fail(uuid_format): + mocked_settings = deepcopy(django_settings.DJANGO_GUID) + mocked_settings['UUID_FORMAT'] = uuid_format + with override_settings(DJANGO_GUID=mocked_settings): + with pytest.raises(ImproperlyConfigured, match='UUID_FORMAT must be either hex, int, or string'): + Settings().validate() + + def test_converts_correctly(): mocked_settings = deepcopy(django_settings.DJANGO_GUID) mocked_settings['IGNORE_URLS'] = ['/no-guid', '/my/api/path/'] From b8c3e27457d06f2492ac4ede6f76115c77005b67 Mon Sep 17 00:00:00 2001 From: Marcelo Lino Date: Tue, 3 May 2022 10:17:51 -0300 Subject: [PATCH 02/11] Fix lint format --- docs/settings.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/settings.rst b/docs/settings.rst index 1026bff..08c0a2e 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -91,4 +91,4 @@ UUID_LENGTH If a UUID hex is not suitable for you, this settings lets you specify the format you wish to use. The options are: * ``hex``: The default, a 32 character hexadecimal string. * ``int``: A 128 bit integer. -* ``str``: A 36 character string. \ No newline at end of file +* ``str``: A 36 character string. From 9dbd4832a2d1967702ddb953e1b8291495aa622a Mon Sep 17 00:00:00 2001 From: Marcelo Lino Date: Tue, 3 May 2022 10:28:50 -0300 Subject: [PATCH 03/11] Change UUID_LENGHT per type --- django_guid/config.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/django_guid/config.py b/django_guid/config.py index 0659c1d..bfe104c 100644 --- a/django_guid/config.py +++ b/django_guid/config.py @@ -1,5 +1,6 @@ # flake8: noqa: D102 -from typing import List, Union +from collections import defaultdict +from typing import Dict, List, Union from django.conf import settings as django_settings from django.core.exceptions import ImproperlyConfigured @@ -58,7 +59,8 @@ def integration_settings(self) -> IntegrationSettings: @property def uuid_length(self) -> int: - return self.settings.get('UUID_LENGTH', 36) + default_lenth: Dict[str, int] = defaultdict(lambda: 32, hex=32, string=36) + return self.settings.get('UUID_LENGTH', default_lenth[self.uuid_format]) @property def uuid_format(self) -> str: From 8e31d6ace592eb9e849da719dbfdd075f06aa04c Mon Sep 17 00:00:00 2001 From: Marcelo Lino Date: Tue, 3 May 2022 10:45:55 -0300 Subject: [PATCH 04/11] Change default UUID_LENGHT for different types --- django_guid/config.py | 8 ++++++-- tests/unit/test_config.py | 30 +++++++++++++++++++++++------- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/django_guid/config.py b/django_guid/config.py index bfe104c..f765470 100644 --- a/django_guid/config.py +++ b/django_guid/config.py @@ -81,8 +81,12 @@ def validate(self) -> None: raise ImproperlyConfigured('IGNORE_URLS must be an array') if not all(isinstance(url, str) for url in self.settings.get('IGNORE_URLS', [])): raise ImproperlyConfigured('IGNORE_URLS must be an array of strings') - if type(self.uuid_length) is not int or not 1 <= self.uuid_length <= 36: - raise ImproperlyConfigured('UUID_LENGTH must be an integer and be between 1-36') + if type(self.uuid_length) is not int or self.uuid_length < 1: + raise ImproperlyConfigured('UUID_LENGTH must be an integer and positive') + if self.uuid_format == 'string' and not 1 <= self.uuid_length <= 36: + raise ImproperlyConfigured('UUID_LENGTH must be between 1-36 when UUID_FORMAT is string') + if self.uuid_format == 'hex' and not 1 <= self.uuid_length <= 32: + raise ImproperlyConfigured('UUID_LENGTH must be between 1-32 when UUID_FORMAT is hex') if self.uuid_format not in ('hex', 'string', 'int'): raise ImproperlyConfigured('UUID_FORMAT must be either hex, int, or string') diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py index 028275c..429d38e 100644 --- a/tests/unit/test_config.py +++ b/tests/unit/test_config.py @@ -8,6 +8,10 @@ from django_guid.config import Settings +UUID_LENGTH_IS_NOT_INTEGER = 'UUID_LENGTH must be an integer and positive' +UUID_LENGHT_IS_NOT_CORRECT_RANGE_HEX_FORMAT = 'UUID_LENGTH must be between 1-32 when UUID_FORMAT is hex' +UUID_LENGHT_IS_NOT_CORRECT_RANGE_STRING_FORMAT = 'UUID_LENGTH must be between 1-36 when UUID_FORMAT is string' + @override_settings() def test_no_config(settings): @@ -86,13 +90,25 @@ def test_not_string_in_igore_urls(): Settings().validate() -def test_uuid_len_fail(): - for setting in [True, False, {}, [], 'asd', -1, 0, 37]: - mocked_settings = deepcopy(django_settings.DJANGO_GUID) - mocked_settings['UUID_LENGTH'] = setting - with override_settings(DJANGO_GUID=mocked_settings): - with pytest.raises(ImproperlyConfigured, match='UUID_LENGTH must be an integer and be between 1-36'): - Settings().validate() +@pytest.mark.parametrize( + 'uuid_length,uuid_format,error_message', + [ + (True, 'hex', UUID_LENGTH_IS_NOT_INTEGER), + (False, 'hex', UUID_LENGTH_IS_NOT_INTEGER), + ({}, 'hex', UUID_LENGTH_IS_NOT_INTEGER), + (-1, 'hex', UUID_LENGTH_IS_NOT_INTEGER), + (0, 'hex', UUID_LENGTH_IS_NOT_INTEGER), + (33, 'hex', UUID_LENGHT_IS_NOT_CORRECT_RANGE_HEX_FORMAT), + (37, 'string', UUID_LENGHT_IS_NOT_CORRECT_RANGE_STRING_FORMAT), + ], +) +def test_uuid_len_fail(uuid_length, uuid_format, error_message): + mocked_settings = deepcopy(django_settings.DJANGO_GUID) + mocked_settings['UUID_LENGTH'] = uuid_length + mocked_settings['UUID_FORMAT'] = uuid_format + with override_settings(DJANGO_GUID=mocked_settings): + with pytest.raises(ImproperlyConfigured, match=error_message): + Settings().validate() @pytest.mark.parametrize('uuid_format', ['bytes', 'urn', 'bytes_le']) From 5a71b5b604d753280c7da65aacb2e40366720b60 Mon Sep 17 00:00:00 2001 From: Marcelo Lino Date: Tue, 3 May 2022 11:13:43 -0300 Subject: [PATCH 05/11] Drop INT support --- django_guid/config.py | 4 ++-- django_guid/utils.py | 4 ++-- docs/settings.rst | 5 ++--- tests/unit/test_config.py | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/django_guid/config.py b/django_guid/config.py index f765470..a790872 100644 --- a/django_guid/config.py +++ b/django_guid/config.py @@ -87,8 +87,8 @@ def validate(self) -> None: raise ImproperlyConfigured('UUID_LENGTH must be between 1-36 when UUID_FORMAT is string') if self.uuid_format == 'hex' and not 1 <= self.uuid_length <= 32: raise ImproperlyConfigured('UUID_LENGTH must be between 1-32 when UUID_FORMAT is hex') - if self.uuid_format not in ('hex', 'string', 'int'): - raise ImproperlyConfigured('UUID_FORMAT must be either hex, int, or string') + if self.uuid_format not in ('hex', 'string'): + raise ImproperlyConfigured('UUID_FORMAT must be either hex or string') self._validate_and_setup_integrations() diff --git a/django_guid/utils.py b/django_guid/utils.py index 3105eda..4ed04ae 100644 --- a/django_guid/utils.py +++ b/django_guid/utils.py @@ -74,10 +74,10 @@ def generate_guid(uuid_length: Optional[int] = None) -> str: if settings.uuid_format == 'string': guid = str(guid) else: - guid = str(getattr(guid, settings.uuid_format)) + guid = getattr(guid, settings.uuid_format) if uuid_length is None: - return guid[: settings.uuid_length] + return guid[:settings.uuid_length] return guid[:uuid_length] diff --git a/docs/settings.rst b/docs/settings.rst index 08c0a2e..8543e78 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -89,6 +89,5 @@ UUID_LENGTH * **Type**: ``string`` If a UUID hex is not suitable for you, this settings lets you specify the format you wish to use. The options are: -* ``hex``: The default, a 32 character hexadecimal string. -* ``int``: A 128 bit integer. -* ``str``: A 36 character string. +* ``hex``: The default, a 32 character hexadecimal string. e.g. ee586b0fba3c44849d20e1548210c050 +* ``str``: A 36 character string. e.g. ee586b0f-ba3c-4484-9d20-e1548210c050 diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py index 429d38e..9966e8e 100644 --- a/tests/unit/test_config.py +++ b/tests/unit/test_config.py @@ -116,7 +116,7 @@ def test_uuid_format_fail(uuid_format): mocked_settings = deepcopy(django_settings.DJANGO_GUID) mocked_settings['UUID_FORMAT'] = uuid_format with override_settings(DJANGO_GUID=mocked_settings): - with pytest.raises(ImproperlyConfigured, match='UUID_FORMAT must be either hex, int, or string'): + with pytest.raises(ImproperlyConfigured, match='UUID_FORMAT must be either hex or string'): Settings().validate() From ac31c38527f626f449b4858a98a115c470b77f91 Mon Sep 17 00:00:00 2001 From: Marcelo Lino Date: Tue, 3 May 2022 11:14:16 -0300 Subject: [PATCH 06/11] Change range test for different formats --- tests/unit/test_uuid_length.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/unit/test_uuid_length.py b/tests/unit/test_uuid_length.py index dc4928f..346bc19 100644 --- a/tests/unit/test_uuid_length.py +++ b/tests/unit/test_uuid_length.py @@ -1,3 +1,4 @@ +import pytest from django.conf import settings as django_settings from django.test import override_settings @@ -13,13 +14,16 @@ def test_uuid_length(): assert len(guid) == i -def test_uuid_length_setting(): +@pytest.mark.parametrize('maximum_range,uuid_format,expected_type', [(33, 'hex', str), (37, 'string', str)]) +def test_uuid_length_setting(maximum_range, uuid_format, expected_type): """ Make sure that the settings value is used as a default. """ - for i in range(33): - mocked_settings = django_settings.DJANGO_GUID - mocked_settings['UUID_LENGTH'] = i + mocked_settings = django_settings.DJANGO_GUID + mocked_settings['UUID_FORMAT'] = uuid_format + for uuid_lenght in range(33): + mocked_settings['UUID_LENGTH'] = uuid_lenght with override_settings(DJANGO_GUID=mocked_settings): guid = generate_guid() - assert len(guid) == i + assert isinstance(guid, expected_type) + assert len(guid) == uuid_lenght From f59cea3cb9b7e1b463066ce5cafa2f7d89e3924f Mon Sep 17 00:00:00 2001 From: Marcelo Lino Date: Tue, 3 May 2022 11:16:38 -0300 Subject: [PATCH 07/11] Fix type check --- django_guid/utils.py | 5 ++--- tests/unit/test_uuid_length.py | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/django_guid/utils.py b/django_guid/utils.py index 4ed04ae..0d972ba 100644 --- a/django_guid/utils.py +++ b/django_guid/utils.py @@ -70,11 +70,10 @@ def generate_guid(uuid_length: Optional[int] = None) -> str: :return: GUID """ - guid = uuid.uuid4() if settings.uuid_format == 'string': - guid = str(guid) + guid = str(uuid.uuid4()) else: - guid = getattr(guid, settings.uuid_format) + guid = uuid.uuid4().hex if uuid_length is None: return guid[:settings.uuid_length] diff --git a/tests/unit/test_uuid_length.py b/tests/unit/test_uuid_length.py index 346bc19..d4e7432 100644 --- a/tests/unit/test_uuid_length.py +++ b/tests/unit/test_uuid_length.py @@ -1,7 +1,8 @@ -import pytest from django.conf import settings as django_settings from django.test import override_settings +import pytest + from django_guid.utils import generate_guid From 36609336e479cf1b4b61b3e983284770aac2c1b4 Mon Sep 17 00:00:00 2001 From: Marcelo Lino Date: Tue, 3 May 2022 11:18:00 -0300 Subject: [PATCH 08/11] Change default UUID_LENGHT documentation --- docs/settings.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/settings.rst b/docs/settings.rst index 8543e78..4c002d8 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -76,7 +76,7 @@ URL endpoints where the middleware will be disabled. You can put your health che UUID_LENGTH ----------- -* **Default**: ``36`` +* **Default**: ``32`` * **Type**: ``int`` If a full UUID hex is too long for you, this settings lets you specify the length you wish to use. From bc9f18d05148bc46c3684c6be492662722b64069 Mon Sep 17 00:00:00 2001 From: Marcelo Lino Date: Tue, 3 May 2022 17:57:15 -0300 Subject: [PATCH 09/11] Change defaultdict parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sondre Lillebø Gundersen --- django_guid/config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/django_guid/config.py b/django_guid/config.py index a790872..60bc830 100644 --- a/django_guid/config.py +++ b/django_guid/config.py @@ -59,8 +59,8 @@ def integration_settings(self) -> IntegrationSettings: @property def uuid_length(self) -> int: - default_lenth: Dict[str, int] = defaultdict(lambda: 32, hex=32, string=36) - return self.settings.get('UUID_LENGTH', default_lenth[self.uuid_format]) + default_length: Dict[str, int] = defaultdict(lambda: 32, string=36) + return self.settings.get('UUID_LENGTH', default_length[self.uuid_format]) @property def uuid_format(self) -> str: From dc55a0be44a472c7c2fe83a3fc110a29e554a709 Mon Sep 17 00:00:00 2001 From: Marcelo Lino Date: Thu, 5 May 2022 14:22:32 -0300 Subject: [PATCH 10/11] Add more tests using string guid --- tests/conftest.py | 3 + tests/functional/test_sync_middleware.py | 71 ++++++++++++++++-------- 2 files changed, 52 insertions(+), 22 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 35ed2c4..98b78ef 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,6 +8,9 @@ def mock_uuid(monkeypatch): class MockUUid: hex = '704ae5472cae4f8daa8f2cc5a5a8mock' + def __str__(self): + return f'{self.hex[:8]}-{self.hex[8:12]}-{self.hex[12:16]}-{self.hex[16:20]}-{self.hex[20:]}' + monkeypatch.setattr('django_guid.utils.uuid.uuid4', MockUUid) diff --git a/tests/functional/test_sync_middleware.py b/tests/functional/test_sync_middleware.py index adbefaf..7a7fd3b 100644 --- a/tests/functional/test_sync_middleware.py +++ b/tests/functional/test_sync_middleware.py @@ -8,7 +8,11 @@ from django_guid.config import Settings -def test_request_with_no_correlation_id(client, caplog, mock_uuid): +@pytest.mark.parametrize( + 'uuid_data,uuid_format', + [('704ae5472cae4f8daa8f2cc5a5a8mock', 'hex'), ('704ae547-2cae-4f8d-aa8f-2cc5a5a8mock', 'string')], +) +def test_request_with_no_correlation_id(uuid_data, uuid_format, client, caplog, mock_uuid, monkeypatch): """ Tests a request without any correlation-ID in it logs the correct things. In this case, it means that the first log message should not have any correlation-ID in it, but the next two @@ -17,58 +21,81 @@ def test_request_with_no_correlation_id(client, caplog, mock_uuid): :param client: Django client :param caplog: caplog fixture """ - response = client.get('/') + mocked_settings = {'GUID_HEADER_NAME': 'Correlation-ID', 'VALIDATE_GUID': False, 'UUID_FORMAT': uuid_format} + + with override_settings(DJANGO_GUID=mocked_settings): + settings = Settings() + monkeypatch.setattr('django_guid.utils.settings', settings) + response = client.get('/') + expected = [ ('sync middleware called', None), ( - 'Header `Correlation-ID` was not found in the incoming request. ' - 'Generated new GUID: 704ae5472cae4f8daa8f2cc5a5a8mock', + 'Header `Correlation-ID` was not found in the incoming request. ' f'Generated new GUID: {uuid_data}', None, ), - ('This log message should have a GUID', '704ae5472cae4f8daa8f2cc5a5a8mock'), - ('Some warning in a function', '704ae5472cae4f8daa8f2cc5a5a8mock'), - ('Received signal `request_finished`, clearing guid', '704ae5472cae4f8daa8f2cc5a5a8mock'), + ('This log message should have a GUID', uuid_data), + ('Some warning in a function', uuid_data), + ('Received signal `request_finished`, clearing guid', uuid_data), ] assert [(x.message, x.correlation_id) for x in caplog.records] == expected - assert response['Correlation-ID'] == '704ae5472cae4f8daa8f2cc5a5a8mock' + assert response['Correlation-ID'] == uuid_data -def test_request_with_correlation_id(client, caplog): +@pytest.mark.parametrize( + 'uuid_data,uuid_format', + [('97c304252fd14b25b72d6aee31565843', 'hex'), ('97c30425-2fd1-4b25-b72d-6aee31565843', 'string')], +) +def test_request_with_correlation_id(uuid_data, uuid_format, client, caplog, monkeypatch): """ Tests a request _with_ a correlation-ID in it logs the correct things. :param client: Django client :param caplog: caplog fixture """ - response = client.get('/', **{'HTTP_Correlation-ID': '97c304252fd14b25b72d6aee31565843'}) + mocked_settings = {'GUID_HEADER_NAME': 'Correlation-ID', 'UUID_FORMAT': uuid_format} + + with override_settings(DJANGO_GUID=mocked_settings): + settings = Settings() + monkeypatch.setattr('django_guid.utils.settings', settings) + response = client.get('/', **{'HTTP_Correlation-ID': uuid_data}) expected = [ ('sync middleware called', None), ('Correlation-ID found in the header', None), - ('97c304252fd14b25b72d6aee31565843 is a valid GUID', None), - ('This log message should have a GUID', '97c304252fd14b25b72d6aee31565843'), - ('Some warning in a function', '97c304252fd14b25b72d6aee31565843'), - ('Received signal `request_finished`, clearing guid', '97c304252fd14b25b72d6aee31565843'), + (f'{uuid_data} is a valid GUID', None), + ('This log message should have a GUID', uuid_data), + ('Some warning in a function', uuid_data), + ('Received signal `request_finished`, clearing guid', uuid_data), ] assert [(x.message, x.correlation_id) for x in caplog.records] == expected - assert response['Correlation-ID'] == '97c304252fd14b25b72d6aee31565843' + assert response['Correlation-ID'] == uuid_data -def test_request_with_non_alnum_correlation_id(client, caplog, mock_uuid): +@pytest.mark.parametrize( + 'uuid_data,uuid_format', + [('704ae5472cae4f8daa8f2cc5a5a8mock', 'hex'), ('704ae547-2cae-4f8d-aa8f-2cc5a5a8mock', 'string')], +) +def test_request_with_non_alnum_correlation_id(uuid_data, uuid_format, client, caplog, mock_uuid, monkeypatch): """ Tests a request _with_ a correlation-ID in it logs the correct things. :param client: Django client :param caplog: caplog fixture """ - response = client.get('/', **{'HTTP_Correlation-ID': '!"#¤&${jndi:ldap://ondsinnet.no/a}'}) + mocked_settings = {'GUID_HEADER_NAME': 'Correlation-ID', 'UUID_FORMAT': uuid_format} + + with override_settings(DJANGO_GUID=mocked_settings): + settings = Settings() + monkeypatch.setattr('django_guid.utils.settings', settings) + response = client.get('/', **{'HTTP_Correlation-ID': '!"#¤&${jndi:ldap://ondsinnet.no/a}'}) expected = [ ('sync middleware called', None), ('Correlation-ID found in the header', None), - ('Non-alnum Correlation-ID provided. New GUID is 704ae5472cae4f8daa8f2cc5a5a8mock', None), - ('This log message should have a GUID', '704ae5472cae4f8daa8f2cc5a5a8mock'), - ('Some warning in a function', '704ae5472cae4f8daa8f2cc5a5a8mock'), - ('Received signal `request_finished`, clearing guid', '704ae5472cae4f8daa8f2cc5a5a8mock'), + (f'Non-alnum Correlation-ID provided. New GUID is {uuid_data}', None), + ('This log message should have a GUID', uuid_data), + ('Some warning in a function', uuid_data), + ('Received signal `request_finished`, clearing guid', uuid_data), ] assert [(x.message, x.correlation_id) for x in caplog.records] == expected - assert response['Correlation-ID'] == '704ae5472cae4f8daa8f2cc5a5a8mock' + assert response['Correlation-ID'] == uuid_data def test_request_with_invalid_correlation_id(client, caplog, mock_uuid): From e103fb8e0847519571d0070954cf2eb7b4404b39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Kr=C3=BCger=20Svensson?= Date: Fri, 6 May 2022 14:56:12 +0200 Subject: [PATCH 11/11] Version bump --- .pre-commit-config.yaml | 16 ++++------------ django_guid/__init__.py | 2 +- django_guid/utils.py | 2 +- pyproject.toml | 2 +- setup.cfg | 2 ++ 5 files changed, 9 insertions(+), 15 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d125bae..1abd5d5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,11 +1,11 @@ repos: - repo: https://github.com/ambv/black - rev: 22.1.0 + rev: 22.3.0 hooks: - id: black args: ['--quiet'] - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.1.0 + rev: v4.2.0 hooks: - id: check-case-conflict - id: end-of-file-fixer @@ -31,7 +31,7 @@ repos: ] args: ['--enable-extensions=G'] - repo: https://github.com/asottile/pyupgrade - rev: v2.31.0 + rev: v2.32.1 hooks: - id: pyupgrade args: ["--py36-plus"] @@ -42,15 +42,7 @@ repos: files: 'django_guid/.*' - id: isort files: 'tests/.*' - - repo: local - hooks: - - id: rst - name: rst - entry: rst-lint --encoding utf-8 - files: ^(CHANGELOG.rst|README.rst|CONTRIBUTING.rst|CONTRIBUTORS.rst|docs/api.rst|docs/extended_example.rst|docs/index.rst|docs/install.rst/index.rst|docs/integration.rst/index.rst|docs/publish.rst/index.rst|docs/settings.rst/index.rst|docs/troubleshooting.rst)$ - language: python - additional_dependencies: [pygments, restructuredtext_lint] - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.931 + rev: v0.950 hooks: - id: mypy diff --git a/django_guid/__init__.py b/django_guid/__init__.py index 8779bd5..3157732 100644 --- a/django_guid/__init__.py +++ b/django_guid/__init__.py @@ -2,7 +2,7 @@ from django_guid.api import clear_guid, get_guid, set_guid # noqa F401 -__version__ = '3.2.2' +__version__ = '3.3.0' if django.VERSION < (3, 2): default_app_config = 'django_guid.apps.DjangoGuidConfig' diff --git a/django_guid/utils.py b/django_guid/utils.py index 0d972ba..c65f09f 100644 --- a/django_guid/utils.py +++ b/django_guid/utils.py @@ -76,7 +76,7 @@ def generate_guid(uuid_length: Optional[int] = None) -> str: guid = uuid.uuid4().hex if uuid_length is None: - return guid[:settings.uuid_length] + return guid[: settings.uuid_length] return guid[:uuid_length] diff --git a/pyproject.toml b/pyproject.toml index 5f30517..1bc689e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "django-guid" -version = "3.2.2" # Remember to also change __init__.py version +version = "3.3.0" # Remember to also change __init__.py version description = "Middleware that enables single request-response cycle tracing by injecting a unique ID into project logs" authors = ["Jonas Krüger Svensson "] maintainers = ["Sondre Lillebø Gundersen "] diff --git a/setup.cfg b/setup.cfg index 2ad0710..e205183 100644 --- a/setup.cfg +++ b/setup.cfg @@ -34,6 +34,8 @@ ignore = ANN002 # Missing type annotations for **kwargs ANN003 + # Allow Any typing + ANN401 exclude = .git,