Compare commits

..

No commits in common. "7645c85c9d975858b2976ab4775f88b7857d5268" and "9025be28bfba6c6fe49087835b568466355bada7" have entirely different histories.

22 changed files with 126 additions and 143 deletions

View File

@ -1,9 +0,0 @@
import amanuensis.backend.article as artiq
import amanuensis.backend.character as charq
import amanuensis.backend.index as indq
import amanuensis.backend.lexicon as lexiq
import amanuensis.backend.membership as memq
import amanuensis.backend.post as postq
import amanuensis.backend.user as userq
__all__ = ["artiq", "charq", "indq", "lexiq", "memq", "postq", "userq"]

View File

@ -7,7 +7,7 @@ from typing import Optional
from sqlalchemy import select from sqlalchemy import select
from amanuensis.db import * from amanuensis.db import *
from amanuensis.errors import ArgumentError, BackendArgumentTypeError from amanuensis.errors import ArgumentError
def create( def create(
@ -21,11 +21,11 @@ def create(
""" """
# Verify argument types are correct # Verify argument types are correct
if not isinstance(lexicon_id, int): if not isinstance(lexicon_id, int):
raise BackendArgumentTypeError(int, lexicon_id=lexicon_id) raise ArgumentError("lexicon_id")
if not isinstance(user_id, int): if not isinstance(user_id, int):
raise BackendArgumentTypeError(int, user_id=user_id) raise ArgumentError("user_id")
if character_id is not None and not isinstance(character_id, int): if character_id is not None and not isinstance(character_id, int):
raise BackendArgumentTypeError(int, character_id=character_id) raise ArgumentError("character_id")
# Check that the user is a member of this lexicon # Check that the user is a member of this lexicon
mem: Membership = db( mem: Membership = db(

View File

@ -7,7 +7,7 @@ from typing import Optional
from sqlalchemy import select, func from sqlalchemy import select, func
from amanuensis.db import * from amanuensis.db import *
from amanuensis.errors import ArgumentError, BackendArgumentTypeError from amanuensis.errors import ArgumentError
def create( def create(
@ -22,13 +22,13 @@ def create(
""" """
# Verify argument types are correct # Verify argument types are correct
if not isinstance(lexicon_id, int): if not isinstance(lexicon_id, int):
raise BackendArgumentTypeError(int, lexicon_id=lexicon_id) raise ArgumentError("lexicon_id")
if not isinstance(user_id, int): if not isinstance(user_id, int):
raise BackendArgumentTypeError(int, user_id=user_id) raise ArgumentError("user_id")
if not isinstance(name, str): if not isinstance(name, str):
raise BackendArgumentTypeError(str, name=name) raise ArgumentError("name")
if signature is not None and not isinstance(signature, str): if signature is not None and not isinstance(signature, str):
raise BackendArgumentTypeError(str, signature=signature) raise ArgumentError("signature")
# Verify character name is valid # Verify character name is valid
if not name.strip(): if not name.strip():

View File

@ -6,7 +6,7 @@ import re
from typing import Optional from typing import Optional
from amanuensis.db import DbContext, ArticleIndex, IndexType from amanuensis.db import DbContext, ArticleIndex, IndexType
from amanuensis.errors import ArgumentError, BackendArgumentTypeError from amanuensis.errors import ArgumentError
def create( def create(
@ -23,17 +23,17 @@ def create(
""" """
# Verify argument types are correct # Verify argument types are correct
if not isinstance(lexicon_id, int): if not isinstance(lexicon_id, int):
raise BackendArgumentTypeError(int, lexicon_id=lexicon_id) raise ArgumentError("lexicon_id")
if not isinstance(index_type, IndexType): if not isinstance(index_type, IndexType):
raise BackendArgumentTypeError(IndexType, index_type=index_type) raise ArgumentError("index_type")
if not isinstance(pattern, str): if not isinstance(pattern, str):
raise BackendArgumentTypeError(str, pattern=pattern) raise ArgumentError("pattern")
if not isinstance(logical_order, int): if not isinstance(logical_order, int):
raise BackendArgumentTypeError(int, logical_order=logical_order) raise ArgumentError("logical_order")
if not isinstance(display_order, int): if not isinstance(display_order, int):
raise BackendArgumentTypeError(int, display_order=display_order) raise ArgumentError("display_order")
if capacity is not None and not isinstance(capacity, int): if capacity is not None and not isinstance(capacity, int):
raise BackendArgumentTypeError(int, capacity=capacity) raise ArgumentError("capacity")
# Verify the pattern is valid for the index type: # Verify the pattern is valid for the index type:
if index_type == IndexType.CHAR: if index_type == IndexType.CHAR:

View File

@ -8,7 +8,7 @@ from typing import Sequence, Optional
from sqlalchemy import select, func from sqlalchemy import select, func
from amanuensis.db import DbContext, Lexicon, Membership from amanuensis.db import DbContext, Lexicon, Membership
from amanuensis.errors import ArgumentError, BackendArgumentTypeError from amanuensis.errors import ArgumentError
RE_ALPHANUM_DASH_UNDER = re.compile(r"^[A-Za-z0-9-_]*$") RE_ALPHANUM_DASH_UNDER = re.compile(r"^[A-Za-z0-9-_]*$")
@ -25,7 +25,7 @@ def create(
""" """
# Verify name # Verify name
if not isinstance(name, str): if not isinstance(name, str):
raise BackendArgumentTypeError(str, name=name) raise ArgumentError("Lexicon name must be a string")
if not name.strip(): if not name.strip():
raise ArgumentError("Lexicon name must not be blank") raise ArgumentError("Lexicon name must not be blank")
if not RE_ALPHANUM_DASH_UNDER.match(name): if not RE_ALPHANUM_DASH_UNDER.match(name):
@ -34,12 +34,12 @@ def create(
) )
# Verify title # Verify title
if title is not None and not isinstance(title, str): if title is not None and not isinstance(name, str):
raise BackendArgumentTypeError(str, title=title) raise ArgumentError("Lexicon name must be a string")
# Verify prompt # Verify prompt
if not isinstance(prompt, str): if not isinstance(prompt, str):
raise BackendArgumentTypeError(str, prompt=prompt) raise ArgumentError("Lexicon prompt must be a string")
# Query the db to make sure the lexicon name isn't taken # Query the db to make sure the lexicon name isn't taken
if db(select(func.count(Lexicon.id)).where(Lexicon.name == name)).scalar() > 0: if db(select(func.count(Lexicon.id)).where(Lexicon.name == name)).scalar() > 0:
@ -55,6 +55,11 @@ def create(
return new_lexicon return new_lexicon
def from_name(db: DbContext, name: str) -> Lexicon:
"""Get a lexicon by its name."""
return db(select(Lexicon).where(Lexicon.name == name)).scalar_one()
def get_all(db: DbContext) -> Sequence[Lexicon]: def get_all(db: DbContext) -> Sequence[Lexicon]:
"""Get all lexicons.""" """Get all lexicons."""
return db(select(Lexicon)).scalars() return db(select(Lexicon)).scalars()
@ -70,8 +75,3 @@ def get_joined(db: DbContext, user_id: int) -> Sequence[Lexicon]:
def get_public(db: DbContext) -> Sequence[Lexicon]: def get_public(db: DbContext) -> Sequence[Lexicon]:
"""Get all publicly visible lexicons.""" """Get all publicly visible lexicons."""
return db(select(Lexicon).where(Lexicon.public == True)).scalars() return db(select(Lexicon).where(Lexicon.public == True)).scalars()
def try_from_name(db: DbContext, name: str) -> Optional[Lexicon]:
"""Get a lexicon by its name, or None if no such lexicon was found."""
return db(select(Lexicon).where(Lexicon.name == name)).scalar_one_or_none()

View File

@ -6,7 +6,7 @@ from sqlalchemy import select, func
from amanuensis.db import DbContext, Membership from amanuensis.db import DbContext, Membership
from amanuensis.db.models import Lexicon from amanuensis.db.models import Lexicon
from amanuensis.errors import ArgumentError, BackendArgumentTypeError from amanuensis.errors import ArgumentError
def create( def create(
@ -20,11 +20,11 @@ def create(
""" """
# Verify argument types are correct # Verify argument types are correct
if not isinstance(user_id, int): if not isinstance(user_id, int):
raise BackendArgumentTypeError(int, user_id=user_id) raise ArgumentError("user_id")
if not isinstance(lexicon_id, int): if not isinstance(lexicon_id, int):
raise BackendArgumentTypeError(int, lexicon_id=lexicon_id) raise ArgumentError("lexicon_id")
if not isinstance(is_editor, bool): if not isinstance(is_editor, bool):
raise BackendArgumentTypeError(bool, is_editor=is_editor) raise ArgumentError("is_editor")
# Verify user has not already joined lexicon # Verify user has not already joined lexicon
if ( if (

View File

@ -8,7 +8,7 @@ from sqlalchemy import select
from amanuensis.db import DbContext, Post from amanuensis.db import DbContext, Post
from amanuensis.db.models import Lexicon from amanuensis.db.models import Lexicon
from amanuensis.errors import ArgumentError, BackendArgumentTypeError from amanuensis.errors import ArgumentError
def create( def create(
@ -23,15 +23,15 @@ def create(
# Verify lexicon id # Verify lexicon id
if not isinstance(lexicon_id, int): if not isinstance(lexicon_id, int):
raise BackendArgumentTypeError(int, lexicon_id=lexicon_id) raise ArgumentError("Lexicon id must be an integer.")
# Verify user_id # Verify user_id
if user_id is not None and not isinstance(user_id, int): if not (isinstance(user_id, int) or user_id is None):
raise BackendArgumentTypeError(int, user_id=user_id) raise ArgumentError("User id must be an integer.")
# Verify body # Verify body
if not isinstance(body, str): if not isinstance(body, str):
raise BackendArgumentTypeError(str, body=body) raise ArgumentError("Post body must be a string.")
if not body.strip(): if not body.strip():
raise ArgumentError("Post body cannot be empty.") raise ArgumentError("Post body cannot be empty.")

View File

@ -10,7 +10,7 @@ from sqlalchemy import select, func, update
from werkzeug.security import generate_password_hash, check_password_hash from werkzeug.security import generate_password_hash, check_password_hash
from amanuensis.db import DbContext, User from amanuensis.db import DbContext, User
from amanuensis.errors import ArgumentError, BackendArgumentTypeError from amanuensis.errors import ArgumentError
RE_NO_LETTERS = re.compile(r"^[0-9-_]*$") RE_NO_LETTERS = re.compile(r"^[0-9-_]*$")
@ -30,7 +30,7 @@ def create(
""" """
# Verify username # Verify username
if not isinstance(username, str): if not isinstance(username, str):
raise BackendArgumentTypeError(str, username=username) raise ArgumentError("Username must be a string")
if len(username) < 3 or len(username) > 32: if len(username) < 3 or len(username) > 32:
raise ArgumentError("Username must be between 3 and 32 characters") raise ArgumentError("Username must be between 3 and 32 characters")
if RE_NO_LETTERS.match(username): if RE_NO_LETTERS.match(username):
@ -42,18 +42,18 @@ def create(
# Verify password # Verify password
if not isinstance(password, str): if not isinstance(password, str):
raise BackendArgumentTypeError(str, password=password) raise ArgumentError("Password must be a string")
# Verify display name # Verify display name
if display_name is not None and not isinstance(display_name, str): if display_name is not None and not isinstance(display_name, str):
raise BackendArgumentTypeError(str, display_name=display_name) raise ArgumentError("Display name must be a string")
# If display name is not provided, use the username # If display name is not provided, use the username
if not display_name or not display_name.strip(): if not display_name or not display_name.strip():
display_name = username display_name = username
# Verify email # Verify email
if not isinstance(email, str): if not isinstance(email, str):
raise BackendArgumentTypeError(str, email=email) raise ArgumentError("Email must be a string")
# Query the db to make sure the username isn't taken # Query the db to make sure the username isn't taken
if db(select(func.count(User.id)).where(User.username == username)).scalar() > 0: if db(select(func.count(User.id)).where(User.username == username)).scalar() > 0:
@ -71,6 +71,24 @@ def create(
return new_user return new_user
def from_id(db: DbContext, user_id: int) -> Optional[User]:
"""
Get a user by the user's id.
Returns None if no user was found.
"""
user: User = db(select(User).where(User.id == user_id)).scalar_one_or_none()
return user
def from_username(db: DbContext, username: str) -> Optional[User]:
"""
Get a user by the user's username.
Returns None if no user was found.
"""
user: User = db(select(User).where(User.username == username)).scalar_one_or_none()
return user
def get_all(db: DbContext) -> Sequence[User]: def get_all(db: DbContext) -> Sequence[User]:
"""Get all users.""" """Get all users."""
return db(select(User)).scalars() return db(select(User)).scalars()
@ -91,16 +109,6 @@ def password_check(db: DbContext, username: str, password: str) -> bool:
return check_password_hash(user_password_hash, password) return check_password_hash(user_password_hash, password)
def try_from_id(db: DbContext, user_id: int) -> Optional[User]:
"""Get a user by the user's id, or None is no such user was found."""
return db(select(User).where(User.id == user_id)).scalar_one_or_none()
def try_from_username(db: DbContext, username: str) -> Optional[User]:
"""Get a user by the user's username, or None is no such user was found."""
return db(select(User).where(User.username == username)).scalar_one_or_none()
def update_logged_in(db: DbContext, username: str) -> None: def update_logged_in(db: DbContext, username: str) -> None:
"""Bump the value of the last_login column for a user.""" """Bump the value of the last_login column for a user."""
db( db(

View File

@ -2,7 +2,9 @@ import logging
from sqlalchemy import update from sqlalchemy import update
from amanuensis.backend import lexiq, memq, userq import amanuensis.backend.lexicon as lexiq
import amanuensis.backend.membership as memq
import amanuensis.backend.user as userq
from amanuensis.db import DbContext, Lexicon from amanuensis.db import DbContext, Lexicon
from .helpers import add_argument from .helpers import add_argument
@ -22,12 +24,9 @@ def command_add(args) -> int:
Add a user to a lexicon. Add a user to a lexicon.
""" """
db: DbContext = args.get_db() db: DbContext = args.get_db()
lexicon = lexiq.try_from_name(db, args.lexicon) lexicon = lexiq.from_name(db, args.lexicon)
if not lexicon: user = userq.from_username(db, args.user)
raise ValueError("Lexicon does not exist") assert user is not None
user = userq.try_from_username(db, args.user)
if not user:
raise ValueError("User does not exist")
memq.create(db, user.id, lexicon.id, args.editor) memq.create(db, user.id, lexicon.id, args.editor)
LOG.info(f"Added {args.user} to lexicon {args.lexicon}") LOG.info(f"Added {args.user} to lexicon {args.lexicon}")
return 0 return 0

View File

@ -1,7 +1,7 @@
import logging import logging
from typing import Optional from typing import Optional
from amanuensis.backend import userq import amanuensis.backend.user as userq
from amanuensis.db import DbContext, User from amanuensis.db import DbContext, User
from .helpers import add_argument from .helpers import add_argument
@ -29,7 +29,7 @@ def command_create(args) -> int:
def command_promote(args) -> int: def command_promote(args) -> int:
"""Make a user a site admin.""" """Make a user a site admin."""
db: DbContext = args.get_db() db: DbContext = args.get_db()
user: Optional[User] = userq.try_from_username(db, args.username) user: Optional[User] = userq.from_username(db, args.username)
if user is None: if user is None:
args.parser.error("User not found") args.parser.error("User not found")
return -1 return -1
@ -46,7 +46,7 @@ def command_promote(args) -> int:
def command_demote(args): def command_demote(args):
"""Revoke a user's site admin status.""" """Revoke a user's site admin status."""
db: DbContext = args.get_db() db: DbContext = args.get_db()
user: Optional[User] = userq.try_from_username(db, args.username) user: Optional[User] = userq.from_username(db, args.username)
if user is None: if user is None:
args.parser.error("User not found") args.parser.error("User not found")
return -1 return -1

View File

@ -4,21 +4,8 @@ Submodule of custom exception types
class AmanuensisError(Exception): class AmanuensisError(Exception):
"""Base class for exceptions in Amanuensis""" """Base class for exceptions in amanuensis"""
class ArgumentError(AmanuensisError): class ArgumentError(AmanuensisError):
"""An internal call was made with invalid arguments.""" """An internal call was made with invalid arguments"""
class BackendArgumentTypeError(ArgumentError):
"""
A call to a backend function was made with a value of an invalid type for the parameter.
Specify the invalid parameter and value as a kwarg.
"""
def __init__(self, obj_type, **kwarg):
if not kwarg:
raise ValueError("Missing kwarg")
param, value = next(iter(kwarg.items()))
msg = f"Expected {param} of type {obj_type}, got {type(value)}"
super().__init__(msg)

View File

@ -2,33 +2,16 @@ from datetime import datetime, timezone
import json import json
import os import os
from flask import Flask, g, url_for from flask import Flask, g
from amanuensis.backend import lexiq, userq, memq import amanuensis.backend.lexicon
import amanuensis.backend.user
from amanuensis.config import AmanuensisConfig, CommandLineConfig from amanuensis.config import AmanuensisConfig, CommandLineConfig
from amanuensis.db import DbContext from amanuensis.db import DbContext
from amanuensis.parser import filesafe_title
import amanuensis.server.auth as auth import amanuensis.server.auth as auth
import amanuensis.server.home as home import amanuensis.server.home as home
def date_format(dt: datetime, formatstr="%Y-%m-%d %H:%M:%S%z") -> str:
"""Convert datetime to human-readable string"""
if dt is None:
return "never"
# Cast db time to UTC, then convert to local timezone
adjusted = dt.replace(tzinfo=timezone.utc).astimezone()
return adjusted.strftime(formatstr)
def article_link(title):
"""Get the url for a lexicon by its title"""
return url_for(
'lexicon.article',
name=g.lexicon.name,
title=filesafe_title(title))
def get_app( def get_app(
config: AmanuensisConfig, config: AmanuensisConfig,
db: DbContext = None, db: DbContext = None,
@ -66,12 +49,20 @@ def get_app(
app.teardown_appcontext(db_teardown) app.teardown_appcontext(db_teardown)
# Configure jinja options # Configure jinja options
def include_backend():
return {"db": db, "lexiq": lexiq, "userq": userq, "memq": memq}
app.jinja_options.update(trim_blocks=True, lstrip_blocks=True) app.jinja_options.update(trim_blocks=True, lstrip_blocks=True)
def date_format(dt: datetime, formatstr="%Y-%m-%d %H:%M:%S%z") -> str:
if dt is None:
return "never"
# Cast db time to UTC, then convert to local timezone
adjusted = dt.replace(tzinfo=timezone.utc).astimezone()
return adjusted.strftime(formatstr)
app.template_filter("date")(date_format) app.template_filter("date")(date_format)
app.template_filter("articlelink")(article_link)
def include_backend():
return {"db": db, "lexiq": amanuensis.backend.lexicon, "userq": amanuensis.backend.user}
app.context_processor(include_backend) app.context_processor(include_backend)
# Set up Flask-Login # Set up Flask-Login

View File

@ -17,7 +17,7 @@ from flask_login import (
LoginManager, LoginManager,
) )
from amanuensis.backend import userq import amanuensis.backend.user as userq
from amanuensis.db import User from amanuensis.db import User
from .forms import LoginForm from .forms import LoginForm
@ -39,7 +39,7 @@ def get_login_manager() -> LoginManager:
user_id = int(user_id_str) user_id = int(user_id_str)
except: except:
return None return None
return userq.try_from_id(g.db, user_id) return userq.from_id(g.db, user_id)
login_manager.user_loader(load_user) login_manager.user_loader(load_user)
@ -58,7 +58,7 @@ def login():
# POST with valid data # POST with valid data
username: str = form.username.data username: str = form.username.data
password: str = form.password.data password: str = form.password.data
user: User = userq.try_from_username(g.db, username) user: User = userq.from_username(g.db, username)
if not user or not userq.password_check(g.db, username, password): if not user or not userq.password_check(g.db, username, password):
# Bad creds # Bad creds
flash("Login not recognized") flash("Login not recognized")

View File

@ -1,6 +1,7 @@
from flask import Blueprint, render_template, g from flask import Blueprint, render_template, g
from amanuensis.backend import userq, lexiq import amanuensis.backend.user as userq
import amanuensis.backend.lexicon as lexiq
# from .forms import LexiconCreateForm # from .forms import LexiconCreateForm

View File

@ -1,9 +1,9 @@
import pytest import pytest
import time import time
from amanuensis.backend import artiq from amanuensis.db import DbContext
from amanuensis.db import DbContext, Character, Lexicon, User from amanuensis.db.models import Character, Lexicon, User
import amanuensis.backend.article as artiq
from amanuensis.errors import ArgumentError from amanuensis.errors import ArgumentError
from tests.conftest import ObjectFactory from tests.conftest import ObjectFactory

View File

@ -1,8 +1,8 @@
import pytest import pytest
from amanuensis.backend import charq
from amanuensis.db import * from amanuensis.db import *
from amanuensis.errors import ArgumentError, BackendArgumentTypeError import amanuensis.backend.character as charq
from amanuensis.errors import ArgumentError
def test_create_character(db: DbContext, lexicon_with_editor, make): def test_create_character(db: DbContext, lexicon_with_editor, make):
@ -20,13 +20,13 @@ def test_create_character(db: DbContext, lexicon_with_editor, make):
kwargs: dict kwargs: dict
# Bad argument types # Bad argument types
with pytest.raises(BackendArgumentTypeError): with pytest.raises(ArgumentError):
kwargs = {**defaults, "name": b"bytestring"} kwargs = {**defaults, "name": b"bytestring"}
charq.create(**kwargs) charq.create(**kwargs)
with pytest.raises(BackendArgumentTypeError): with pytest.raises(ArgumentError):
kwargs = {**defaults, "name": None} kwargs = {**defaults, "name": None}
charq.create(**kwargs) charq.create(**kwargs)
with pytest.raises(BackendArgumentTypeError): with pytest.raises(ArgumentError):
kwargs = {**defaults, "signature": b"bytestring"} kwargs = {**defaults, "signature": b"bytestring"}
charq.create(**kwargs) charq.create(**kwargs)

View File

@ -1,8 +1,8 @@
from amanuensis.db.models import IndexType from amanuensis.db.models import IndexType
import pytest import pytest
from amanuensis.backend import indq import amanuensis.backend.index as indq
from amanuensis.db import DbContext, Lexicon from amanuensis.db import DbContext, Lexicon, User
from amanuensis.errors import ArgumentError from amanuensis.errors import ArgumentError

View File

@ -3,9 +3,9 @@ import time
import pytest import pytest
from amanuensis.backend import lexiq import amanuensis.backend.lexicon as lexiq
from amanuensis.db import DbContext, Lexicon, User from amanuensis.db import DbContext, Lexicon, User
from amanuensis.errors import ArgumentError, BackendArgumentTypeError from amanuensis.errors import ArgumentError
from tests.conftest import ObjectFactory from tests.conftest import ObjectFactory
@ -20,7 +20,7 @@ def test_create_lexicon(db: DbContext):
kwargs: dict kwargs: dict
# Test name constraints # Test name constraints
with pytest.raises(BackendArgumentTypeError): with pytest.raises(ArgumentError):
kwargs = {**defaults, "name": None} kwargs = {**defaults, "name": None}
lexiq.create(**kwargs) lexiq.create(**kwargs)
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
@ -58,8 +58,8 @@ def test_lexicon_from(db: DbContext, make: ObjectFactory):
"""Test lexiq.from_*.""" """Test lexiq.from_*."""
lexicon1: Lexicon = make.lexicon() lexicon1: Lexicon = make.lexicon()
lexicon2: Lexicon = make.lexicon() lexicon2: Lexicon = make.lexicon()
assert lexiq.try_from_name(db, lexicon1.name) == lexicon1 assert lexiq.from_name(db, lexicon1.name) == lexicon1
assert lexiq.try_from_name(db, lexicon2.name) == lexicon2 assert lexiq.from_name(db, lexicon2.name) == lexicon2
def test_get_lexicon(db: DbContext, make: ObjectFactory): def test_get_lexicon(db: DbContext, make: ObjectFactory):

View File

@ -2,9 +2,9 @@ import pytest
from sqlalchemy import select from sqlalchemy import select
from amanuensis.backend import memq
from amanuensis.db import * from amanuensis.db import *
from amanuensis.errors import ArgumentError from amanuensis.errors import ArgumentError
import amanuensis.backend.membership as memq
def test_create_membership(db: DbContext, make): def test_create_membership(db: DbContext, make):

View File

@ -1,9 +1,9 @@
import pytest import pytest
from amanuensis.backend import postq
from amanuensis.db import DbContext from amanuensis.db import DbContext
import amanuensis.backend.post as postq
from amanuensis.errors import ArgumentError, BackendArgumentTypeError from amanuensis.errors import ArgumentError
def test_create_post(db: DbContext, lexicon_with_editor): def test_create_post(db: DbContext, lexicon_with_editor):
@ -20,16 +20,19 @@ def test_create_post(db: DbContext, lexicon_with_editor):
kwargs: dict kwargs: dict
# ids are integers # ids are integers
with pytest.raises(BackendArgumentTypeError): with pytest.raises(ArgumentError):
kwargs = {**defaults, "user_id": "zero"} kwargs = {**defaults, "user_id": "zero"}
postq.create(**kwargs) postq.create(**kwargs)
with pytest.raises(BackendArgumentTypeError): with pytest.raises(ArgumentError):
kwargs = {**defaults, "lexicon_id": "zero"} kwargs = {**defaults, "lexicon_id": "zero"}
postq.create(**kwargs) postq.create(**kwargs)
# empty arguments don't work # empty arguments don't work
with pytest.raises(BackendArgumentTypeError): with pytest.raises(ArgumentError):
kwargs = {**defaults, "lexicon_id": None} kwargs = {**defaults, "lexicon_id": ""}
postq.create(**kwargs)
with pytest.raises(ArgumentError):
kwargs = {**defaults, "user_id": ""}
postq.create(**kwargs) postq.create(**kwargs)
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
kwargs = {**defaults, "body": ""} kwargs = {**defaults, "body": ""}

View File

@ -2,9 +2,9 @@ import os
import pytest import pytest
from amanuensis.backend import userq import amanuensis.backend.user as userq
from amanuensis.db import DbContext, User from amanuensis.db import DbContext, User
from amanuensis.errors import ArgumentError, BackendArgumentTypeError from amanuensis.errors import ArgumentError
def test_create_user(db: DbContext): def test_create_user(db: DbContext):
@ -33,7 +33,7 @@ def test_create_user(db: DbContext):
userq.create(**kwargs) userq.create(**kwargs)
# No password # No password
with pytest.raises(BackendArgumentTypeError): with pytest.raises(ArgumentError):
kwargs = {**defaults, "password": None} kwargs = {**defaults, "password": None}
userq.create(**kwargs) userq.create(**kwargs)
@ -57,10 +57,10 @@ def test_user_from(db: DbContext, make):
"""Test userq.from_*.""" """Test userq.from_*."""
user1: User = make.user() user1: User = make.user()
user2: User = make.user() user2: User = make.user()
assert userq.try_from_id(db, user1.id) == user1 assert userq.from_id(db, user1.id) == user1
assert userq.try_from_username(db, user1.username) == user1 assert userq.from_username(db, user1.username) == user1
assert userq.try_from_id(db, user2.id) == user2 assert userq.from_id(db, user2.id) == user2
assert userq.try_from_username(db, user2.username) == user2 assert userq.from_username(db, user2.username) == user2
def test_user_password(db: DbContext, make): def test_user_password(db: DbContext, make):

View File

@ -10,7 +10,10 @@ from bs4 import BeautifulSoup
from flask.testing import FlaskClient from flask.testing import FlaskClient
from sqlalchemy.orm.session import close_all_sessions from sqlalchemy.orm.session import close_all_sessions
from amanuensis.backend import charq, lexiq, memq, userq import amanuensis.backend.character as charq
import amanuensis.backend.lexicon as lexiq
import amanuensis.backend.membership as memq
import amanuensis.backend.user as userq
from amanuensis.config import AmanuensisConfig from amanuensis.config import AmanuensisConfig
from amanuensis.db import DbContext, User, Lexicon, Membership, Character from amanuensis.db import DbContext, User, Lexicon, Membership, Character
from amanuensis.server import get_app from amanuensis.server import get_app
@ -42,7 +45,7 @@ class UserClient:
def login(self, client: FlaskClient): def login(self, client: FlaskClient):
"""Log the user in.""" """Log the user in."""
user: Optional[User] = userq.try_from_id(self.db, self.user_id) user: Optional[User] = userq.from_id(self.db, self.user_id)
assert user is not None assert user is not None
# Set the user's password so we know what it is later # Set the user's password so we know what it is later