Adopt mypy as a static type checker #7
@ -2,13 +2,20 @@
|
||||
Article query interface
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from sqlalchemy import select
|
||||
|
||||
from amanuensis.db import *
|
||||
from amanuensis.errors import ArgumentError
|
||||
|
||||
|
||||
def create(db: DbContext, lexicon_id: int, user_id: int, character_id: int) -> Article:
|
||||
def create(
|
||||
db: DbContext,
|
||||
lexicon_id: int,
|
||||
user_id: int,
|
||||
character_id: Optional[int],
|
||||
) -> Article:
|
||||
"""
|
||||
Create a new article in a lexicon.
|
||||
"""
|
||||
|
@ -2,6 +2,8 @@
|
||||
Character query interface
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from sqlalchemy import select, func
|
||||
|
||||
from amanuensis.db import *
|
||||
@ -9,7 +11,11 @@ from amanuensis.errors import ArgumentError
|
||||
|
||||
|
||||
def create(
|
||||
db: DbContext, lexicon_id: int, user_id: int, name: str, signature: str
|
||||
db: DbContext,
|
||||
lexicon_id: int,
|
||||
user_id: int,
|
||||
name: str,
|
||||
signature: Optional[str],
|
||||
) -> Character:
|
||||
"""
|
||||
Create a new character for a user.
|
||||
|
@ -13,7 +13,12 @@ from amanuensis.errors import ArgumentError
|
||||
RE_ALPHANUM_DASH_UNDER = re.compile(r"^[A-Za-z0-9-_]*$")
|
||||
|
||||
|
||||
def create(db: DbContext, name: str, title: str, prompt: str) -> Lexicon:
|
||||
def create(
|
||||
db: DbContext,
|
||||
name: str,
|
||||
title: str,
|
||||
prompt: str,
|
||||
) -> Lexicon:
|
||||
"""
|
||||
Create a new lexicon.
|
||||
"""
|
||||
|
@ -8,7 +8,12 @@ from amanuensis.db import DbContext, Membership
|
||||
from amanuensis.errors import ArgumentError
|
||||
|
||||
|
||||
def create(db: DbContext, user_id: int, lexicon_id: int, is_editor: bool) -> Membership:
|
||||
def create(
|
||||
db: DbContext,
|
||||
user_id: int,
|
||||
lexicon_id: int,
|
||||
is_editor: bool,
|
||||
) -> Membership:
|
||||
"""
|
||||
Create a new user membership in a lexicon.
|
||||
"""
|
||||
|
@ -10,7 +10,12 @@ from amanuensis.db import DbContext, Post
|
||||
from amanuensis.errors import ArgumentError
|
||||
|
||||
|
||||
def create(db: DbContext, lexicon_id: int, user_id: int, body: str) -> Post:
|
||||
def create(
|
||||
db: DbContext,
|
||||
lexicon_id: int,
|
||||
user_id: int,
|
||||
body: str,
|
||||
) -> Post:
|
||||
"""
|
||||
Create a new post
|
||||
"""
|
||||
|
@ -11,7 +11,7 @@ import amanuensis.backend.user as userq
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def db():
|
||||
def db() -> DbContext:
|
||||
"""Provides an initialized database in memory."""
|
||||
db = DbContext("sqlite:///:memory:", debug=False)
|
||||
db.create_all()
|
||||
|
@ -1,6 +1,7 @@
|
||||
import pytest
|
||||
|
||||
from amanuensis.db import DbContext
|
||||
from amanuensis.db.models import Character, Lexicon, User
|
||||
import amanuensis.backend.article as artiq
|
||||
|
||||
from amanuensis.errors import ArgumentError
|
||||
@ -9,18 +10,18 @@ from amanuensis.errors import ArgumentError
|
||||
def test_create_article(db: DbContext, make):
|
||||
"""Test new article creation"""
|
||||
# Create two users in a shared lexicon
|
||||
user1 = make.user()
|
||||
user2 = make.user()
|
||||
lexicon1 = make.lexicon()
|
||||
user1: User = make.user()
|
||||
user2: User = make.user()
|
||||
lexicon1: Lexicon = make.lexicon()
|
||||
make.membership(user_id=user1.id, lexicon_id=lexicon1.id)
|
||||
make.membership(user_id=user2.id, lexicon_id=lexicon1.id)
|
||||
char1_1 = make.character(lexicon_id=lexicon1.id, user_id=user1.id)
|
||||
char1_2 = make.character(lexicon_id=lexicon1.id, user_id=user2.id)
|
||||
char1_1: Character = make.character(lexicon_id=lexicon1.id, user_id=user1.id)
|
||||
char1_2: Character = make.character(lexicon_id=lexicon1.id, user_id=user2.id)
|
||||
|
||||
# Create a lexicon that only one user is in
|
||||
lexicon2 = make.lexicon()
|
||||
lexicon2: Lexicon = make.lexicon()
|
||||
make.membership(user_id=user2.id, lexicon_id=lexicon2.id)
|
||||
char2_2 = make.character(lexicon_id=lexicon2.id, user_id=user2.id)
|
||||
char2_2: Character = make.character(lexicon_id=lexicon2.id, user_id=user2.id)
|
||||
|
||||
# User cannot create article for another user's character
|
||||
with pytest.raises(ArgumentError):
|
||||
|
@ -7,35 +7,44 @@ from amanuensis.errors import ArgumentError
|
||||
|
||||
def test_create_character(db: DbContext, lexicon_with_editor, make):
|
||||
"""Test creating a character."""
|
||||
lexicon: Lexicon
|
||||
user: User
|
||||
lexicon, user = lexicon_with_editor
|
||||
kwargs = {
|
||||
defaults: dict = {
|
||||
"db": db,
|
||||
"user_id": user.id,
|
||||
"lexicon_id": lexicon.id,
|
||||
"name": "Character Name",
|
||||
"signature": "Signature",
|
||||
}
|
||||
kwargs: dict
|
||||
|
||||
# Bad argument types
|
||||
with pytest.raises(ArgumentError):
|
||||
charq.create(**{**kwargs, "name": b"bytestring"})
|
||||
kwargs = {**defaults, "name": b"bytestring"}
|
||||
charq.create(**kwargs)
|
||||
with pytest.raises(ArgumentError):
|
||||
charq.create(**{**kwargs, "name": None})
|
||||
kwargs = {**defaults, "name": None}
|
||||
charq.create(**kwargs)
|
||||
with pytest.raises(ArgumentError):
|
||||
charq.create(**{**kwargs, "signature": b"bytestring"})
|
||||
kwargs = {**defaults, "signature": b"bytestring"}
|
||||
charq.create(**kwargs)
|
||||
|
||||
# Bad character name
|
||||
with pytest.raises(ArgumentError):
|
||||
charq.create(**{**kwargs, "name": " "})
|
||||
kwargs = {**defaults, "name": " "}
|
||||
charq.create(**kwargs)
|
||||
|
||||
# Signature is auto-populated
|
||||
char = charq.create(**{**kwargs, "signature": None})
|
||||
kwargs = {**defaults, "signature": None}
|
||||
char = charq.create(**kwargs)
|
||||
assert char.signature is not None
|
||||
|
||||
# User must be in lexicon
|
||||
new_user = make.user()
|
||||
new_user: User = make.user()
|
||||
with pytest.raises(ArgumentError):
|
||||
charq.create(**{**kwargs, "user_id": new_user.id})
|
||||
kwargs = {**defaults, "user_id": new_user.id}
|
||||
charq.create(**kwargs)
|
||||
|
||||
|
||||
def test_character_limits(db: DbContext, lexicon_with_editor):
|
||||
@ -47,12 +56,14 @@ def test_character_limits(db: DbContext, lexicon_with_editor):
|
||||
# Set character limit to one and create a character
|
||||
lexicon.character_limit = 1
|
||||
db.session.commit()
|
||||
char1 = charq.create(db, lexicon.id, user.id, "Test Character 1", signature=None)
|
||||
char1: Character = charq.create(
|
||||
db, lexicon.id, user.id, "Test Character 1", signature=None
|
||||
)
|
||||
assert char1.id, "Failed to create character 1"
|
||||
|
||||
# Creating a second character should fail
|
||||
with pytest.raises(ArgumentError):
|
||||
char2 = charq.create(
|
||||
char2: Character = charq.create(
|
||||
db, lexicon.id, user.id, "Test Character 2", signature=None
|
||||
)
|
||||
assert char2
|
||||
@ -65,7 +76,7 @@ def test_character_limits(db: DbContext, lexicon_with_editor):
|
||||
|
||||
# Creating a third character should fail
|
||||
with pytest.raises(ArgumentError):
|
||||
char3 = charq.create(
|
||||
char3: Character = charq.create(
|
||||
db, lexicon.id, user.id, "Test Character 3", signature=None
|
||||
)
|
||||
assert char3
|
||||
|
@ -1,3 +1,4 @@
|
||||
from amanuensis.db.models import Lexicon
|
||||
import datetime
|
||||
|
||||
import pytest
|
||||
@ -9,24 +10,37 @@ from amanuensis.errors import ArgumentError
|
||||
|
||||
def test_create_lexicon(db: DbContext):
|
||||
"""Test new game creation."""
|
||||
kwargs = {"name": "Test", "title": None, "prompt": "A test Lexicon game"}
|
||||
defaults: dict = {
|
||||
"db": db,
|
||||
"name": "Test",
|
||||
"title": None,
|
||||
"prompt": "A test Lexicon game",
|
||||
}
|
||||
kwargs: dict
|
||||
|
||||
# Test name constraints
|
||||
with pytest.raises(ArgumentError):
|
||||
lexiq.create(db, **{**kwargs, "name": None})
|
||||
kwargs = {**defaults, "name": None}
|
||||
lexiq.create(**kwargs)
|
||||
with pytest.raises(ArgumentError):
|
||||
lexiq.create(db, **{**kwargs, "name": ""})
|
||||
kwargs = {**defaults, "name": ""}
|
||||
lexiq.create(**kwargs)
|
||||
with pytest.raises(ArgumentError):
|
||||
lexiq.create(db, **{**kwargs, "name": " "})
|
||||
kwargs = {**defaults, "name": " "}
|
||||
lexiq.create(**kwargs)
|
||||
with pytest.raises(ArgumentError):
|
||||
lexiq.create(db, **{**kwargs, "name": ".."})
|
||||
kwargs = {**defaults, "name": ".."}
|
||||
lexiq.create(**kwargs)
|
||||
with pytest.raises(ArgumentError):
|
||||
lexiq.create(db, **{**kwargs, "name": "\x00"})
|
||||
kwargs = {**defaults, "name": "\x00"}
|
||||
lexiq.create(**kwargs)
|
||||
with pytest.raises(ArgumentError):
|
||||
lexiq.create(db, **{**kwargs, "name": "space in name"})
|
||||
kwargs = {**defaults, "name": "space in name"}
|
||||
lexiq.create(**kwargs)
|
||||
|
||||
# Validate that creation populates fields, including timestamps
|
||||
before = datetime.datetime.utcnow() - datetime.timedelta(seconds=1)
|
||||
new_lexicon = lexiq.create(db, **kwargs)
|
||||
new_lexicon: Lexicon = lexiq.create(**defaults)
|
||||
after = datetime.datetime.utcnow() + datetime.timedelta(seconds=1)
|
||||
assert new_lexicon
|
||||
assert new_lexicon.id is not None
|
||||
@ -36,5 +50,4 @@ def test_create_lexicon(db: DbContext):
|
||||
|
||||
# No duplicate lexicon names
|
||||
with pytest.raises(ArgumentError):
|
||||
duplicate = lexiq.create(db, **kwargs)
|
||||
assert duplicate
|
||||
lexiq.create(**defaults)
|
||||
|
@ -10,13 +10,13 @@ import amanuensis.backend.membership as memq
|
||||
def test_create_membership(db: DbContext, make):
|
||||
"""Test joining a game."""
|
||||
# Set up a user and a lexicon
|
||||
new_user = make.user()
|
||||
new_user: User = make.user()
|
||||
assert new_user.id, "Failed to create user"
|
||||
new_lexicon = make.lexicon()
|
||||
new_lexicon: Lexicon = make.lexicon()
|
||||
assert new_lexicon.id, "Failed to create lexicon"
|
||||
|
||||
# Add the user to the lexicon as an editor
|
||||
mem = memq.create(db, new_user.id, new_lexicon.id, True)
|
||||
mem: Membership = memq.create(db, new_user.id, new_lexicon.id, True)
|
||||
assert mem, "Failed to create membership"
|
||||
|
||||
# Check that the user and lexicon are mutually visible in the ORM relationships
|
||||
@ -24,7 +24,7 @@ def test_create_membership(db: DbContext, make):
|
||||
assert any(map(lambda mem: mem.user == new_user, new_lexicon.memberships))
|
||||
|
||||
# Check that the editor flag was set properly
|
||||
editor = db(
|
||||
editor: User = db(
|
||||
select(User)
|
||||
.join(User.memberships)
|
||||
.join(Membership.lexicon)
|
||||
@ -37,5 +37,4 @@ def test_create_membership(db: DbContext, make):
|
||||
|
||||
# Check that joining twice is not allowed
|
||||
with pytest.raises(ArgumentError):
|
||||
mem2 = memq.create(db, new_user.id, new_lexicon.id, False)
|
||||
assert mem2
|
||||
memq.create(db, new_user.id, new_lexicon.id, False)
|
||||
|
@ -11,34 +11,47 @@ def test_create_post(db: DbContext, lexicon_with_editor):
|
||||
lexicon, editor = lexicon_with_editor
|
||||
|
||||
# argument dictionary for post object
|
||||
kwargs = {"lexicon_id": lexicon.id, "user_id": editor.id, "body": "body"}
|
||||
defaults: dict = {
|
||||
"db": db,
|
||||
"lexicon_id": lexicon.id,
|
||||
"user_id": editor.id,
|
||||
"body": "body",
|
||||
}
|
||||
kwargs: dict
|
||||
|
||||
# ids are integers
|
||||
with pytest.raises(ArgumentError):
|
||||
postq.create(db, **{**kwargs, "user_id": "zero"})
|
||||
kwargs = {**defaults, "user_id": "zero"}
|
||||
postq.create(**kwargs)
|
||||
with pytest.raises(ArgumentError):
|
||||
postq.create(db, **{**kwargs, "lexicon_id": "zero"})
|
||||
kwargs = {**defaults, "lexicon_id": "zero"}
|
||||
postq.create(**kwargs)
|
||||
|
||||
# empty arguments don't work
|
||||
with pytest.raises(ArgumentError):
|
||||
postq.create(db, **{**kwargs, "lexicon_id": ""})
|
||||
kwargs = {**defaults, "lexicon_id": ""}
|
||||
postq.create(**kwargs)
|
||||
with pytest.raises(ArgumentError):
|
||||
postq.create(db, **{**kwargs, "user_id": ""})
|
||||
kwargs = {**defaults, "user_id": ""}
|
||||
postq.create(**kwargs)
|
||||
with pytest.raises(ArgumentError):
|
||||
postq.create(db, **{**kwargs, "body": ""})
|
||||
kwargs = {**defaults, "body": ""}
|
||||
postq.create(**kwargs)
|
||||
|
||||
# post with only whitespace doesn't work
|
||||
with pytest.raises(ArgumentError):
|
||||
postq.create(db, **{**kwargs, "body": " "})
|
||||
kwargs = {**defaults, "body": " "}
|
||||
postq.create(**kwargs)
|
||||
|
||||
# post creation works and populates fields
|
||||
new_post = postq.create(db, **kwargs)
|
||||
new_post = postq.create(**defaults)
|
||||
assert new_post
|
||||
assert new_post.lexicon_id is not None
|
||||
assert new_post.user_id is not None
|
||||
assert new_post.body is not None
|
||||
|
||||
# post creation works when user is None
|
||||
new_post = postq.create(db, **{**kwargs, "user_id": None})
|
||||
kwargs = {**defaults, "user_id": None}
|
||||
new_post = postq.create(**kwargs)
|
||||
assert new_post
|
||||
assert new_post.user_id is None
|
||||
|
@ -1,3 +1,4 @@
|
||||
from amanuensis.db.models import User
|
||||
import pytest
|
||||
|
||||
from amanuensis.db import DbContext
|
||||
@ -7,39 +8,45 @@ from amanuensis.errors import ArgumentError
|
||||
|
||||
def test_create_user(db: DbContext):
|
||||
"""Test new user creation."""
|
||||
kwargs = {
|
||||
defaults: dict = {
|
||||
"db": db,
|
||||
"username": "username",
|
||||
"password": "password",
|
||||
"display_name": "User Name",
|
||||
"email": "user@example.com",
|
||||
"is_site_admin": False,
|
||||
}
|
||||
kwargs: dict
|
||||
|
||||
# Test length constraints
|
||||
with pytest.raises(ArgumentError):
|
||||
userq.create(db, **{**kwargs, "username": "me"})
|
||||
kwargs = {**defaults, "username": "me"}
|
||||
userq.create(**kwargs)
|
||||
with pytest.raises(ArgumentError):
|
||||
userq.create(
|
||||
db, **{**kwargs, "username": "the right honorable user-name, esquire"}
|
||||
)
|
||||
kwargs = {**defaults, "username": "the right honorable user-name, esquire"}
|
||||
userq.create(**kwargs)
|
||||
|
||||
# Test allowed characters
|
||||
with pytest.raises(ArgumentError):
|
||||
userq.create(db, **{**kwargs, "username": "user name"})
|
||||
kwargs = {**defaults, "username": "user name"}
|
||||
userq.create(**kwargs)
|
||||
|
||||
# No password
|
||||
with pytest.raises(ArgumentError):
|
||||
userq.create(db, **{**kwargs, "password": None})
|
||||
kwargs = {**defaults, "password": None}
|
||||
userq.create(**kwargs)
|
||||
|
||||
# Valid creation works and populates fields
|
||||
new_user = userq.create(db, **kwargs)
|
||||
new_user = userq.create(**defaults)
|
||||
assert new_user
|
||||
assert new_user.id is not None
|
||||
assert new_user.created is not None
|
||||
|
||||
# No duplicate usernames
|
||||
with pytest.raises(ArgumentError):
|
||||
duplicate = userq.create(db, **kwargs)
|
||||
userq.create(**defaults)
|
||||
|
||||
# Missing display name populates with username
|
||||
user2_kw = {**kwargs, "username": "user2", "display_name": None}
|
||||
user2 = userq.create(db, **user2_kw)
|
||||
user2_kw: dict = {**defaults, "username": "user2", "display_name": None}
|
||||
user2: User = userq.create(**user2_kw)
|
||||
assert user2.display_name is not None
|
||||
|
Loading…
Reference in New Issue
Block a user