Additional tests
This commit is contained in:
parent
3a9ef9cae7
commit
2a63c37856
@ -1,7 +1,7 @@
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
||||||
def apply(change, string, categories={}, apply=True):
|
def apply(change, string, categories={}, apply=True, zero_characters=['∅']):
|
||||||
"""Apply a sound change to a given string"""
|
"""Apply a sound change to a given string"""
|
||||||
|
|
||||||
if not apply:
|
if not apply:
|
||||||
@ -10,12 +10,11 @@ def apply(change, string, categories={}, apply=True):
|
|||||||
# Check validity of change
|
# Check validity of change
|
||||||
if change.count('>') != 1:
|
if change.count('>') != 1:
|
||||||
raise ValueError(f"Change {change} is not a valid sound change. (Missing character '>')")
|
raise ValueError(f"Change {change} is not a valid sound change. (Missing character '>')")
|
||||||
|
|
||||||
if change.count('/') > 1:
|
if change.count('/') > 1:
|
||||||
raise ValueError(f"Change {change} is not a valid sound change. (More than one '/' character)")
|
raise ValueError(f"Change {change} is not a valid sound change. (More than one '/' character)")
|
||||||
|
|
||||||
# Prepare change for regex
|
# Prepare change for regex
|
||||||
for k, v in {'{': '(', '}': ')', ',': '|'}.items():
|
for k, v in {' ': '', '{': '(', '}': ')', ',': '|'}.items():
|
||||||
change = change.replace(k, v)
|
change = change.replace(k, v)
|
||||||
|
|
||||||
# Replacements for categories
|
# Replacements for categories
|
||||||
@ -30,15 +29,24 @@ def apply(change, string, categories={}, apply=True):
|
|||||||
else:
|
else:
|
||||||
environment = '_'
|
environment = '_'
|
||||||
|
|
||||||
|
# Collaplse multiple underscores
|
||||||
|
environment = re.sub('(_+)', '_', environment)
|
||||||
|
|
||||||
if environment.count('_') != 1:
|
if environment.count('_') != 1:
|
||||||
raise ValueError(f"Environment {environment} is not a valid environment. (Character '_' should exist exactly once)")
|
raise ValueError(f"Environment {environment} is not a valid environment. (Character '_' should exist exactly once)")
|
||||||
|
|
||||||
original, change_to = change.split('>')
|
original, change_to = change.split('>')
|
||||||
before, after = environment.split('_')
|
before, after = environment.split('_')
|
||||||
|
|
||||||
n = before.count('(') + original.count('(') + 3
|
if not original:
|
||||||
|
raise ValueError(f"Nothing to change from.")
|
||||||
|
|
||||||
|
# Remove zero characters
|
||||||
|
for char in zero_characters:
|
||||||
|
change_to = change_to.replace(char, '')
|
||||||
|
|
||||||
pattern = f"({before})({original})({after})"
|
pattern = f"({before})({original})({after})"
|
||||||
repl = f"\\1{change_to}\\{n}"
|
last_group_index = pattern.count('(') - after.count('(')
|
||||||
|
replacement = f"\\1{change_to}\\{last_group_index}"
|
||||||
return re.sub(pattern, repl, f"#{string}#").strip('#')
|
|
||||||
|
|
||||||
|
return re.sub(pattern, replacement, f"#{string}#").strip('#')
|
||||||
|
|||||||
@ -1,13 +1,43 @@
|
|||||||
from soundchanger.change import apply
|
from soundchanger.change import apply
|
||||||
|
|
||||||
|
|
||||||
def test_apply_without_environment():
|
def test_without_environment():
|
||||||
assert apply('p>h', 'pana') == 'hana'
|
assert apply('p>h', 'pana') == 'hana'
|
||||||
|
|
||||||
def test_apply_with_environment():
|
def test_with_environment():
|
||||||
assert apply('p>f/#_u', 'pune') == 'fune'
|
assert apply('p>f/#_u', 'pune') == 'fune'
|
||||||
|
|
||||||
def test_apply_with_complex_environment():
|
def test_with_partial_environment():
|
||||||
|
assert apply('p>h/#_', 'pi') == 'hi'
|
||||||
|
assert apply('p>h/_i', 'pi') == 'hi'
|
||||||
|
|
||||||
|
def test_change_to_nothing():
|
||||||
|
assert apply('u>', 'fun') == 'fn'
|
||||||
|
|
||||||
|
def test_change_to_nothing_with_environment():
|
||||||
|
assert apply('u>/_n#', 'fun') == 'fn'
|
||||||
|
|
||||||
|
def test_change_to_zero_character_with_environment():
|
||||||
|
assert apply('w>∅', 'kawa') == 'kaa'
|
||||||
|
|
||||||
|
def test_custom_zero_character():
|
||||||
|
assert apply('w>-', 'kawa', zero_characters=['-']) == 'kaa'
|
||||||
|
|
||||||
|
def test_whitespace_in_change():
|
||||||
|
assert apply(' a > b / c _ d ', 'cad') == 'cbd'
|
||||||
|
|
||||||
|
def test_multiple_underscores_in_environment():
|
||||||
|
assert apply('a>b/c___d ', 'cad') == 'cbd'
|
||||||
|
|
||||||
|
def test_categories_as_string():
|
||||||
|
assert apply('V>o', 'ha', categories={'V': 'aiu'}) == 'ho'
|
||||||
|
assert apply('V>o', 'he', categories={'V': 'aiu'}) == 'he'
|
||||||
|
|
||||||
|
def test_categories_as_list():
|
||||||
|
assert apply('V>o', 'ha', categories={'V': ['a', 'i', 'u']}) == 'ho'
|
||||||
|
assert apply('V>o', 'he', categories={'V': ['a', 'i', 'u']}) == 'he'
|
||||||
|
|
||||||
|
def test_complex_environment():
|
||||||
inputs = ['pana', 'pina', 'puna', 'pama', 'pima', 'puma']
|
inputs = ['pana', 'pina', 'puna', 'pama', 'pima', 'puma']
|
||||||
outputs = ['pana', 'hina', 'huna', 'pama', 'hima', 'huma']
|
outputs = ['pana', 'hina', 'huna', 'pama', 'hima', 'huma']
|
||||||
for string, output in zip(inputs, outputs):
|
for string, output in zip(inputs, outputs):
|
||||||
@ -17,14 +47,14 @@ def test_apply_with_complex_environment():
|
|||||||
categories={'N': 'nm'}
|
categories={'N': 'nm'}
|
||||||
) == output
|
) == output
|
||||||
|
|
||||||
def test_apply_with_complex_group_and_categories():
|
def test_complex_group_and_categories():
|
||||||
assert apply('e>i/{#,p,t,k}V{m,n,h}_#', 'pane', categories={
|
assert apply('e>i/{#,p,t,k}V{m,n,h}_#', 'pane', categories={
|
||||||
'V': 'aiu',
|
'V': 'aiu',
|
||||||
'P': 'ptk',
|
'P': 'ptk',
|
||||||
'N': 'mn',
|
'N': 'mn',
|
||||||
}) == 'pani'
|
}) == 'pani'
|
||||||
|
|
||||||
def test_apply_with_complex_group_and_categories_and_digraphs():
|
def test_with_complex_group_and_categories_and_digraphs():
|
||||||
assert apply('u>o/#V{ts,pf,t}_k{V,e,o}#', 'atsuka', categories={
|
assert apply('u>o/#V{ts,pf,t}_k{V,e,o}#', 'atsuka', categories={
|
||||||
'V': ['a', 'i', 'u']
|
'V': ['a', 'i', 'u']
|
||||||
}) == 'atsoka'
|
}) == 'atsoka'
|
||||||
@ -34,3 +64,14 @@ def test_apply_with_complex_group_and_categories_and_digraphs():
|
|||||||
assert apply('u>o/#V{ts,pf,t}_k{V,e,o}#', 'matsuka', categories={
|
assert apply('u>o/#V{ts,pf,t}_k{V,e,o}#', 'matsuka', categories={
|
||||||
'V': ['a', 'i', 'u']
|
'V': ['a', 'i', 'u']
|
||||||
}) == 'matsuka'
|
}) == 'matsuka'
|
||||||
|
|
||||||
|
def test_multiple_changes():
|
||||||
|
string = 'pana'
|
||||||
|
for change in ['p>f', 'n>m/fa_']:
|
||||||
|
string = apply(change, string)
|
||||||
|
assert string == 'fama'
|
||||||
|
|
||||||
|
def test_change_from_category():
|
||||||
|
assert apply('V>o', 'tatiru', categories={
|
||||||
|
'V': 'aiu'
|
||||||
|
}) == 'totoro'
|
||||||
|
|||||||
@ -2,14 +2,18 @@ import pytest
|
|||||||
import re
|
import re
|
||||||
from soundchanger.change import apply
|
from soundchanger.change import apply
|
||||||
|
|
||||||
def test_parse_change_error_change():
|
def test_error_in_change():
|
||||||
with pytest.raises(ValueError, match=re.escape("Change is not a valid sound change. (Missing character '>')")):
|
with pytest.raises(ValueError, match=re.escape("Change is not a valid sound change. (Missing character '>')")):
|
||||||
apply('', '')
|
apply('', '')
|
||||||
|
|
||||||
def test_apply_error_split():
|
def test_error_split():
|
||||||
with pytest.raises(ValueError, match=re.escape("Change a>b/c/d is not a valid sound change. (More than one '/' character)")):
|
with pytest.raises(ValueError, match=re.escape("Change a>b/c/d is not a valid sound change. (More than one '/' character)")):
|
||||||
apply('a>b/c/d', '')
|
apply('a>b/c/d', '')
|
||||||
|
|
||||||
def test_apply_error_environment():
|
def test_error_in_environment():
|
||||||
with pytest.raises(ValueError, match=re.escape("Environment c is not a valid environment. (Character '_' should exist exactly once)")):
|
with pytest.raises(ValueError, match=re.escape("Environment c is not a valid environment. (Character '_' should exist exactly once)")):
|
||||||
apply('a>b/c', '')
|
apply('a>b/c', '')
|
||||||
|
|
||||||
|
def test_no_change_from():
|
||||||
|
with pytest.raises(ValueError, match=re.escape("Nothing to change from.")):
|
||||||
|
apply('>b', '')
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user