diff --git a/env_spec.py b/env_spec.py index 11da659..6ae5c3f 100644 --- a/env_spec.py +++ b/env_spec.py @@ -6,7 +6,9 @@ class EnvSpecSyntaxError(Exception): Excpetion used for syntax errors. """ - pass + def __init__(self, message, line): + super().__init__(message) + self.line = line valid_types_list = [ @@ -124,42 +126,49 @@ def parse(env_spec_text): comment_regex = r"^(.+)\#(.+)$" lines = env_spec_text.split("\n") + print(lines) + enumerated_list = enumerate(lines) - for line in lines: + for line in enumerated_list: + line_number = line[0] + env_spec_line = line[1] env_spec_entry = {} - line_comment_match = re.match(line_comment_regex, line) + line_comment_match = re.match(line_comment_regex, env_spec_line) if line_comment_match: continue env_spec_entry["comment"] = None - comment_match = re.match(comment_regex, line) + comment_match = re.match(comment_regex, env_spec_line) if comment_match: - line = comment_match.groups()[0] + env_spec_line = comment_match.groups()[0] comment = comment_match.groups()[1] env_spec_entry["comment"] = comment - name_match = re.match(name_regex, line) + name_match = re.match(name_regex, env_spec_line) if name_match: name = name_match.groups()[0] - line = name_match.groups()[1] + env_spec_line = name_match.groups()[1] is_variable_name_valid = re.match( alphanumeric_that_does_not_start_with_digit, name ) if not is_variable_name_valid: - raise EnvSpecSyntaxError("SYNTAX ERROR: Invalid variable name.") + raise EnvSpecSyntaxError( + "Invalid variable name; it should contain only latin alphanumeric characters, underscores and not start with a digit.", + line_number, + ) env_spec_entry["name"] = name env_spec_entry["choices"] = None env_spec_entry["default_value"] = None - choices_match = re.match(choices_regex, line) - default_value_match = re.match(default_values_regex, line) + choices_match = re.match(choices_regex, env_spec_line) + default_value_match = re.match(default_values_regex, env_spec_line) if choices_match: choices_str = choices_match.groups()[0] @@ -167,7 +176,9 @@ def parse(env_spec_text): choices = create_list(choices_str) if not choices: - raise EnvSpecSyntaxError("SYNTAX ERROR: Invalid choices list.") + raise EnvSpecSyntaxError( + "Invalid restricted choices syntax.", line_number + ) env_spec_entry["choices"] = choices @@ -177,7 +188,10 @@ def parse(env_spec_text): if choices_match: if default_value not in choices or default_value == "": - raise EnvSpecSyntaxError("SYNTAX ERROR: Invalid default value.") + raise EnvSpecSyntaxError( + "Invalid default value; it is not included in the provided restricted choices.", + line_number, + ) env_spec_entry["default_value"] = default_value @@ -185,24 +199,31 @@ def parse(env_spec_text): if default_value_match: env_spec_type = default_value_match.groups()[0] else: - env_spec_type = line + env_spec_type = env_spec_line env_spec_type = env_spec_type.strip() if env_spec_type not in valid_types_list: - raise EnvSpecSyntaxError("SYNTAX ERROR: Invalid type.") + raise EnvSpecSyntaxError( + "Invalid variable type; it should be one of: \n" + + (", ".join(map(str, valid_types_list))), + line_number, + ) env_spec_entry["type"] = env_spec_type else: env_spec_entry["type"] = "text" else: - name = line.strip() + name = env_spec_line.strip() is_variable_name_valid = re.match( alphanumeric_that_does_not_start_with_digit, name ) if not is_variable_name_valid: - raise EnvSpecSyntaxError("SYNTAX ERROR: Invalid variable name.") + raise EnvSpecSyntaxError( + "Invalid variable name; it should contain only latin alphanumeric characters, underscores and not start with a digit.", + line_number, + ) env_spec_entry["name"] = name env_spec_entry["type"] = "text" @@ -230,5 +251,5 @@ def main(): if __name__ == "__main__": - spec_str = "# This line will be ignored\nADMIN_EMAIL: email # This email will be notified for occurring errors" + spec_str = "DATABASE_URL: testing" print(main()) diff --git a/env_spec_test.py b/env_spec_test.py index 726432e..9350a3c 100644 --- a/env_spec_test.py +++ b/env_spec_test.py @@ -5,19 +5,25 @@ def test_invalid_input_non_latin(): with pytest.raises(env_spec.EnvSpecSyntaxError) as excinfo: env_spec.parse("dαtabase_url") - assert "SYNTAX ERROR: Invalid variable name." in str(excinfo.value) + assert ( + "Invalid variable name; it should contain only latin alphanumeric characters, underscores and not start with a digit." + in str(excinfo.value) + ) def test_invalid_input_start_with_digit(): with pytest.raises(env_spec.EnvSpecSyntaxError) as excinfo: env_spec.parse("1DATABASE_URL: url") - assert "SYNTAX ERROR: Invalid variable name." in str(excinfo.value) + assert ( + "Invalid variable name; it should contain only latin alphanumeric characters, underscores and not start with a digit." + in str(excinfo.value) + ) def test_non_existed_type(): with pytest.raises(env_spec.EnvSpecSyntaxError) as excinfo: env_spec.parse("DATABASE_URL: testing") - assert "SYNTAX ERROR: Invalid type." in str(excinfo.value) + assert "Invalid variable type; it should be one of: " in str(excinfo.value) def test_valid_input_types(): @@ -56,7 +62,10 @@ def test_wrong_default_values(): env_spec.parse( "DEBUG: [0,1]=1\nENVIRONMENT: [production,staging,development]=develoent" ) - assert "SYNTAX ERROR: Invalid default value." in str(excinfo.value) + assert ( + "Invalid default value; it is not included in the provided restricted choices." + in str(excinfo.value) + ) def test_default_values(): diff --git a/test.py b/test.py new file mode 100644 index 0000000..19ba682 --- /dev/null +++ b/test.py @@ -0,0 +1,8 @@ +lines = [ + "DEBUG: [0,1]= 1", + "ENVIRONMENT: [production,staging,development]= development", +] +enumerated = enumerate(lines) + +for line in enumerated: + print(line[0])