membership.create() checks for joinable and player limit; factory creates joinable lexicons by default #10

Closed
nvb wants to merge 2 commits from nvb/membership-create into develop
2 changed files with 124 additions and 0 deletions
Showing only changes of commit 9c75141342 - Show all commits

View File

@ -0,0 +1,74 @@
"""
Index query interface
"""
import re
from typing import Optional
from amanuensis.db import DbContext, ArticleIndex, IndexType
from amanuensis.errors import ArgumentError
def create(
db: DbContext,
lexicon_id: int,
index_type: IndexType,
pattern: str,
logical_order: int,
display_order: int,
capacity: Optional[int],
) -> ArticleIndex:
"""
Create a new index in a lexicon.
"""
# Verify argument types are correct
if not isinstance(lexicon_id, int):
raise ArgumentError("lexicon_id")
if not isinstance(index_type, IndexType):
raise ArgumentError("index_type")
if not isinstance(pattern, str):
raise ArgumentError("pattern")
if not isinstance(logical_order, int):
raise ArgumentError("logical_order")
if not isinstance(display_order, int):
raise ArgumentError("display_order")
if capacity is not None and not isinstance(capacity, int):
raise ArgumentError("capacity")
# Verify the pattern is valid for the index type:
if index_type == IndexType.CHAR:
if len(pattern) < 1:
raise ArgumentError(
f"Pattern '{pattern}' too short for index type {index_type}"
)
elif index_type == IndexType.RANGE:
range_def = re.match(r"^(.)-(.)$", pattern)
if not range_def:
raise ArgumentError(f"Pattern '{pattern}' is not a valid range format")
start_char, end_char = range_def.group(1), range_def.group(2)
if start_char >= end_char:
raise ArgumentError(
f"Range start '{start_char}' is not before range end '{end_char}'"
)
elif index_type == IndexType.PREFIX:
if len(pattern) < 1:
raise ArgumentError(
f"Pattern '{pattern}' too short for index type {index_type}"
)
elif index_type == IndexType.ETC:
if len(pattern) < 1:
raise ArgumentError(
f"Pattern '{pattern}' too short for index type {index_type}"
)
new_index = ArticleIndex(
lexicon_id=lexicon_id,
index_type=index_type,
pattern=pattern,
logical_order=logical_order,
display_order=display_order,
capacity=capacity,
)
db.session.add(new_index)
db.session.commit()
return new_index

50
tests/test_index.py Normal file
View File

@ -0,0 +1,50 @@
from amanuensis.db.models import IndexType
import pytest
import amanuensis.backend.index as indq
from amanuensis.db import DbContext, Lexicon, User
from amanuensis.errors import ArgumentError
def test_create_index(db: DbContext, make):
"""Test new index creation"""
lexicon: Lexicon = make.lexicon()
defaults: dict = {
"db": db,
"lexicon_id": lexicon.id,
"index_type": IndexType.ETC,
"pattern": "&c.",
"logical_order": 0,
"display_order": 0,
"capacity": 0,
}
kwargs: dict
# Character indexes require nonempty patterns
with pytest.raises(ArgumentError):
kwargs = {**defaults, "index_type": IndexType.CHAR, "pattern": ""}
indq.create(**kwargs)
kwargs = {**defaults, "index_type": IndexType.CHAR, "pattern": "ABC"}
assert indq.create(**kwargs)
# Range indexes must follow the 1-2 format
with pytest.raises(ArgumentError):
kwargs = {**defaults, "index_type": IndexType.RANGE, "pattern": "ABC"}
indq.create(**kwargs)
kwargs = {**defaults, "index_type": IndexType.RANGE, "pattern": "A-F"}
assert indq.create(**kwargs)
# Prefix indexes require nonempty patterns
with pytest.raises(ArgumentError):
kwargs = {**defaults, "index_type": IndexType.CHAR, "pattern": ""}
indq.create(**kwargs)
kwargs = {**defaults, "index_type": IndexType.CHAR, "pattern": "Prefix:"}
assert indq.create(**kwargs)
# Etc indexes require nonempty patterns
with pytest.raises(ArgumentError):
kwargs = {**defaults, "index_type": IndexType.CHAR, "pattern": ""}
indq.create(**kwargs)
kwargs = {**defaults, "index_type": IndexType.CHAR, "pattern": "&c."}
assert indq.create(**kwargs)