From 24ed37352f8ade76607d49aff3a32bb5582ca356 Mon Sep 17 00:00:00 2001 From: yongfu Date: Fri, 1 Mar 2019 09:33:55 +0800 Subject: [PATCH] fix regular expression with { } like in server_name,rewrite,location and if. --- nginxfmt.py | 38 +++++++++++++++++++++++++++++++------- test_nginxfmt.py | 10 +++++++--- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/nginxfmt.py b/nginxfmt.py index 57a26f6..1dd1771 100755 --- a/nginxfmt.py +++ b/nginxfmt.py @@ -20,6 +20,8 @@ INDENTATION = ' ' * 4 TEMPLATE_VARIABLE_OPENING_TAG = '___TEMPLATE_VARIABLE_OPENING_TAG___' TEMPLATE_VARIABLE_CLOSING_TAG = '___TEMPLATE_VARIABLE_CLOSING_TAG___' +TEMPLATE_REG_OPENING_TAG = '___TEMPLATE_REG_OPENING_TAG___' +TEMPLATE_REG_CLOSING_TAG = '___TEMPLATE_REG_CLOSING_TAG___' def strip_line(single_line): """Strips the line and replaces neighbouring whitespaces with single space (except when within quotation marks).""" @@ -45,7 +47,7 @@ def multi_semicolon(single_line): return single_line, 0 m1 = re.match(r"^([^;#]*;)([\s]*#.*)?$", single_line) - m2 = re.match(r"^([^#]+)(;[\s]*)(#.*)?$", single_line) + m2 = re.match(r"^([^#]+)([;][\s]*)(#.*)?$", single_line) if m1 is not None: return single_line, 0 @@ -74,6 +76,30 @@ def multi_semicolon(single_line): return single_line, 0 +def apply_reg_template_tags(line: str) -> str: + """Replaces rewrite/server_name/if/location regular expression have { } in quotes with tags""" + parts = [] + within_quotes = False + for part in re.split('"', line): + if within_quotes: + part = part.replace("{", TEMPLATE_REG_OPENING_TAG) + part = part.replace("}", TEMPLATE_REG_CLOSING_TAG) + parts.append(part) + else: + parts.append(part) + within_quotes = not within_quotes + + line = '"'.join(parts) + return line + + +def strip_reg_template_tags(line: str) -> str: + """Replaces rewrite/server_name/if/location regular expression have { } in quotes with tags""" + line = line.replace(TEMPLATE_REG_OPENING_TAG, "{") + line = line.replace(TEMPLATE_REG_CLOSING_TAG, "}") + return line + + def apply_variable_template_tags(line: str) -> str: """Replaces variable indicators ${ and } with tags, so subsequent formatting is easier.""" return re.sub(r'\${\s*(\w+)\s*}', @@ -96,22 +122,20 @@ def clean_lines(orig_lines) -> list: for line in orig_lines: line = strip_line(line) line = apply_variable_template_tags(line) + line = apply_reg_template_tags(line) if line == "": cleaned_lines.append("") continue else: if line.startswith("#"): - cleaned_lines.append(strip_variable_template_tags(line)) + cleaned_lines.append(strip_reg_template_tags(strip_variable_template_tags(line))) else: mline, c = multi_semicolon(line) if c > 0: cleaned_lines.extend(clean_lines(mline.splitlines())) else: - if mline.startswith("rewrite"): - cleaned_lines.append(strip_variable_template_tags(mline)) - else: - cleaned_lines.extend( - [strip_variable_template_tags(l).strip() for l in re.split(r"([{}])", mline) if l != ""]) + cleaned_lines.extend( + [strip_reg_template_tags(strip_variable_template_tags(l)).strip() for l in re.split(r"([{}])", mline) if l != ""]) return cleaned_lines diff --git a/test_nginxfmt.py b/test_nginxfmt.py index 20e1dbe..d23aaa5 100644 --- a/test_nginxfmt.py +++ b/test_nginxfmt.py @@ -37,8 +37,8 @@ class TestFormatter(unittest.TestCase): self.assertEqual(["{", "ala", "# ma {{", "kota", "}", "to", "}", "# }"], clean_lines(("{", "ala ", "# ma {{", " kota ", "}", " to} ", "# }"))) - self.assertEqual(["{", "ala", "# ma {{", "rewrite /([\d]{2}) /up/$1.html last;", "}", "to", "}"], - clean_lines(("{", "ala ", "# ma {{", " rewrite /([\d]{2}) /up/$1.html last; ", "}", " to", "}"))) + self.assertEqual(["{", "ala", "# ma {{", "rewrite \"/([\d]{2})\" /up/$1.html last;", "}", "to", "}"], + clean_lines(("{", "ala ", "# ma {{", " rewrite \"/([\d]{2})\" /up/$1.html last; ", "}", " to", "}"))) self.assertEqual(["{", "ala", "# ma {{", "aa last;", "bb to;", "}"], clean_lines(("{", "ala ", "# ma {{", " aa last; bb to; ", "}"))) @@ -48,7 +48,7 @@ class TestFormatter(unittest.TestCase): self.assertEqual(["{", "a aa;", "bb b \"ccc; dddd;\";", "ee e; # ff; ee ;", "}"], clean_lines(("{", "a aa; bb b \"ccc; dddd;\"; ee e; # ff; ee ;", "}"))) - + self.assertEqual(["location ~ /\.ht", "{"], clean_lines(["location ~ /\.ht {", ])) def test_perform_indentation(self): @@ -200,6 +200,10 @@ class TestFormatter(unittest.TestCase): ' deny all;\n' + '}\n') + def test_reg_template_tags(self): + self.assertEqual('server_name "~^(?[0-9a-f]___TEMPLATE_REG_OPENING_TAG___8___TEMPLATE_REG_CLOSING_TAG___)\.a\.b\.com$";', + apply_reg_template_tags('server_name "~^(?[0-9a-f]{8})\.a\.b\.com$";')) + def test_loading_utf8_file(self): tmp_file = tempfile.mkstemp('utf-8')[1] shutil.copy('test-files/umlaut-utf8.conf', tmp_file)