-
Notifications
You must be signed in to change notification settings - Fork 39
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
refactor utils, add tests, move exceptions into separate module #264
base: main
Are you sure you want to change the base?
Changes from 8 commits
5fd2aa8
1d4272d
c1a6e0c
d32f7aa
427cca6
afceb60
489ac0b
168eb00
211249f
bf8be31
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
__all__ = [ | ||
"DDLParserError", | ||
] | ||
|
||
|
||
class DDLParserError(Exception): | ||
""" Base exception in simple ddl parser library """ | ||
pass |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,31 @@ | ||
import re | ||
from typing import List | ||
from typing import List, Tuple, Optional, Union, Any | ||
|
||
__all__ = [ | ||
"remove_par", | ||
"check_spec", | ||
"find_first_unpair_closed_par", | ||
"normalize_name", | ||
"get_table_id", | ||
] | ||
|
||
def remove_par(p_list: List[str]) -> List[str]: | ||
remove_list = ["(", ")"] | ||
for symbol in remove_list: | ||
while symbol in p_list: | ||
p_list.remove(symbol) | ||
_parentheses = ('(', ')') | ||
|
||
|
||
def remove_par(p_list: List[Union[str, Any]]) -> List[Union[str, Any]]: | ||
""" | ||
Remove the parentheses from the given list | ||
|
||
Warn: p_list may contain unhashable types for some unexplored reasons | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's better to find the reason why There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, it is expected, p_list contains results of parsing statements, usually it something like {'column': name, 'unique': True}, so p_list - always list, but elements of this list can be dicts There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I rewrote this docstring then. |
||
""" | ||
i = j = 0 | ||
while i < len(p_list): | ||
if p_list[i] not in _parentheses: | ||
p_list[j] = p_list[i] | ||
j += 1 | ||
i += 1 | ||
while j < len(p_list): | ||
p_list.pop() | ||
return p_list | ||
|
||
|
||
|
@@ -18,44 +37,39 @@ def remove_par(p_list: List[str]) -> List[str]: | |
} | ||
|
||
|
||
# TODO: Add tests | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm gonna add some tests for |
||
def check_spec(value: str) -> str: | ||
replace_value = spec_mapper.get(value) | ||
if not replace_value: | ||
for item in spec_mapper: | ||
if item in value: | ||
replace_value = value.replace(item, spec_mapper[item]) | ||
break | ||
else: | ||
replace_value = value | ||
return replace_value | ||
|
||
|
||
def find_first_unpair_closed_par(str_: str) -> int: | ||
stack = [] | ||
n = -1 | ||
for i in str_: | ||
n += 1 | ||
if i == ")": | ||
if not stack: | ||
return n | ||
else: | ||
stack.pop(-1) | ||
elif i == "(": | ||
stack.append(i) | ||
if replace_value: | ||
return replace_value | ||
for item in spec_mapper: | ||
if item in value: | ||
return value.replace(item, spec_mapper[item]) | ||
return value | ||
|
||
|
||
def find_first_unpair_closed_par(str_: str) -> Optional[int]: | ||
count_open = 0 | ||
for i, char in enumerate(str_): | ||
if char == '(': | ||
count_open += 1 | ||
if char == ')': | ||
count_open -= 1 | ||
if count_open < 0: | ||
return i | ||
return None | ||
|
||
|
||
def normalize_name(name: str) -> str: | ||
# clean up [] and " symbols from names | ||
""" | ||
Clean up [] and " characters from the given name | ||
""" | ||
clean_up_re = r'[\[\]"]' | ||
return re.sub(clean_up_re, "", name).lower() | ||
|
||
|
||
def get_table_id(schema_name: str, table_name: str): | ||
def get_table_id(schema_name: str, table_name: str) -> Tuple[str, str]: | ||
table_name = normalize_name(table_name) | ||
if schema_name: | ||
schema_name = normalize_name(schema_name) | ||
return (table_name, schema_name) | ||
|
||
|
||
class SimpleDDLParserException(Exception): | ||
pass |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import pytest | ||
|
||
from simple_ddl_parser import utils | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"expression, expected_result", | ||
[ | ||
(")", 0), | ||
(")()", 0), | ||
("())", 2), | ||
("()())", 4), | ||
("", None), | ||
("text", None), | ||
("()", None), | ||
("(balanced) (brackets)", None), | ||
("(not)) (balanced) (brackets", 5) | ||
] | ||
) | ||
def test_find_first_unpair_closed_par(expression, expected_result): | ||
assert utils.find_first_unpair_closed_par(expression) == expected_result | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"expression, expected_result", | ||
[ | ||
([], []), | ||
(["("], []), | ||
([")"], []), | ||
(["(", ")"], []), | ||
([")", "("], []), | ||
(["(", "A"], ["A"]), | ||
(["A", ")"], ["A"]), | ||
(["(", "A", ")"], ["A"]), | ||
(["A", ")", ")"], ["A"]), | ||
(["(", "(", "A"], ["A"]), | ||
(["A", "B", "C"], ["A", "B", "C"]), | ||
(["A", "(", "(", "B", "C", "("], ["A", "B", "C"]), | ||
(["A", ")", "B", ")", "(", "C"], ["A", "B", "C"]), | ||
(["(", "A", ")", "B", "C", ")"], ["A", "B", "C"]), | ||
([dict()], [dict()]), # Edge case (unhashable types) | ||
] | ||
) | ||
def test_remove_par(expression, expected_result): | ||
assert utils.remove_par(expression) == expected_result |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure, if someone uses this exception in their code (to catch it in
try-except
, for instance). If, it is possible, then it is more correct to make an alias and deprecate it officially.