diff --git a/docs/releasenotes.md b/docs/releasenotes.md index 7715601..cb31151 100644 --- a/docs/releasenotes.md +++ b/docs/releasenotes.md @@ -1,5 +1,12 @@ # Release Notes +## Unreleased + +### What's new? + +- Fixed the "path matches" condition validator to allow any valid regular expression. + + ## 5.0.3 ### What's new? diff --git a/flags/conditions/__init__.py b/flags/conditions/__init__.py index 7825296..9a747ab 100644 --- a/flags/conditions/__init__.py +++ b/flags/conditions/__init__.py @@ -20,6 +20,6 @@ validate_boolean, validate_date, validate_parameter, - validate_path, + validate_path_re, validate_user, ) diff --git a/flags/conditions/conditions.py b/flags/conditions/conditions.py index 6ae4292..77cb23f 100644 --- a/flags/conditions/conditions.py +++ b/flags/conditions/conditions.py @@ -9,7 +9,7 @@ validate_boolean, validate_date, validate_parameter, - validate_path, + validate_path_re, validate_user, ) @@ -67,7 +67,7 @@ def parameter_condition(param_name, request=None, **kwargs): return request.GET.get(param_name) == param_value -@register("path matches", validator=validate_path) +@register("path matches", validator=validate_path_re) def path_condition(pattern, request=None, **kwargs): """ Does the request's path match the given regular expression? """ if request is None: diff --git a/flags/conditions/validators.py b/flags/conditions/validators.py index 675192d..4307617 100644 --- a/flags/conditions/validators.py +++ b/flags/conditions/validators.py @@ -7,15 +7,6 @@ from django.utils import dateparse -validate_path = RegexValidator( - re.compile(r"^[^\s:?#]+$", re.UNICODE), - message=( - "Enter a valid path without a URL scheme, query string, or fragment." - ), - code="invalid", -) - - validate_parameter = RegexValidator( re.compile(r"^[-_\w=]+$", re.UNICODE), message="Enter a valid HTTP parameter name.", @@ -23,6 +14,16 @@ ) +def validate_path_re(value): + try: + re.compile(value) + except re.error as e: + raise ValidationError( + "Enter either a valid path or a regular expression to match a " + "path, without a URL scheme, query string, or fragment." + ) from e + + def validate_boolean(value): message = "Enter one of 'on', 'off', 'true', 'false', etc." try: diff --git a/flags/tests/test_conditions_validators.py b/flags/tests/test_conditions_validators.py index 5ec26fc..dae7fe0 100644 --- a/flags/tests/test_conditions_validators.py +++ b/flags/tests/test_conditions_validators.py @@ -6,7 +6,7 @@ validate_boolean, validate_date, validate_parameter, - validate_path, + validate_path_re, validate_user, ) @@ -26,18 +26,15 @@ def test_valid_parameter_strings(self): class ValidatePathTestCase(TestCase): - def test_invalid_path_strings(self): + def test_invalid_path_regexs(self): with self.assertRaises(ValidationError): - validate_path("/my/path#foo") - with self.assertRaises(ValidationError): - validate_path("/my/path?foo=bar") - with self.assertRaises(ValidationError): - validate_path("https://foo/my/path") + validate_path_re("*foo/my/path") - def test_valid_path_strings(self): - validate_path("/my/path") - validate_path("/my/path/") - validate_path("my/path/") + def test_valid_path_regexs(self): + validate_path_re("/my/path") + validate_path_re("/my/path/") + validate_path_re("my/path/") + validate_path_re(r"^/my/(path)?$") class ValidateBooleanTestCase(TestCase):