Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
titus-ong committed Aug 23, 2020
1 parent 59c68e4 commit 468a248
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
64 changes: 64 additions & 0 deletions src/chordparser/music/key.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from chordparser.music.notationparser import NotationParser
from chordparser.music.note import NoteNotationParser
from chordparser.utils.regex_patterns import (submode_pattern,
mode_pattern,
short_minor_pattern,
short_major_pattern)


class ModeError(Exception):
"""Exception where a `Key`'s `mode` is invalid."""
pass


class ModeNotationParser(NotationParser):
"""Parse mode notation into mode and submode."""
_pattern = (
fr"(\s?({submode_pattern})?\s?({mode_pattern}))|"
f"({short_minor_pattern})|"
f"({short_major_pattern})"
)

def _split_into_groups(self, regex):
"""Split into mode and submode."""
mode = self._get_mode(
regex.group(3), regex.group(4), regex.group(5)
)
submode = self._get_submode(
regex.group(2), self._is_minor(mode)
)
return mode, submode

def _get_mode(self, long_mode, short_minor, short_major):
if short_major is not None:
return "major"
if short_minor:
return "minor"
return long_mode.lower()

def _is_minor(self, mode):
return mode in ("minor", "aeolian")

def _get_submode(self, submode, is_minor):
if submode and not is_minor:
raise ModeError("Only minor can have a submode")
if not is_minor:
return ""
if is_minor and not submode:
return "natural"
return submode.lower()


class KeyNotationParser:
"""Parse key notation into tonic and mode groups."""
_NNP = NoteNotationParser()
_MNP = ModeNotationParser()
_pattern = (
f"({_NNP.get_regex_pattern})"
f"({_MNP.get_regex_pattern})"
)


class Key:
def __init__(self, notation):
pass
37 changes: 37 additions & 0 deletions tests/test_music/test_key.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import pytest

from chordparser.music.key import (ModeError, ModeNotationParser,
KeyNotationParser, Key)


class TestMNPParseNotation:
@pytest.fixture
def parser(self):
return ModeNotationParser()

@pytest.mark.parametrize(
"notation, expected_mode", [
("", "major"),
("m", "minor"),
(" major", "major"),
(" Dorian", "dorian"),
]
)
def test_correct_mode(self, parser, notation, expected_mode):
mode, _ = parser.parse_notation(notation)
assert expected_mode == mode

@pytest.mark.parametrize(
"notation, expected_submode", [
(" minor", "natural"),
("harmonic minor", "harmonic"),
(" major", ""),
]
)
def test_correct_submode(self, parser, notation, expected_submode):
_, submode = parser.parse_notation(notation)
assert expected_submode == submode

def test_mode_error(self, parser):
with pytest.raises(ModeError):
parser.parse_notation("natural major")

0 comments on commit 468a248

Please sign in to comment.