black string quote normalization

This commit is contained in:
Tim Van Baak 2021-06-02 20:10:34 -07:00
parent de09030b1c
commit 2982f6ea0f
15 changed files with 185 additions and 186 deletions

View File

@ -14,11 +14,11 @@ def create(db: DbContext, lexicon_id: int, user_id: int, character_id: int) -> A
""" """
# Verify argument types are correct # Verify argument types are correct
if not isinstance(lexicon_id, int): if not isinstance(lexicon_id, int):
raise ArgumentError('lexicon_id') raise ArgumentError("lexicon_id")
if not isinstance(user_id, int): if not isinstance(user_id, int):
raise ArgumentError('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 ArgumentError('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(
@ -27,7 +27,7 @@ def create(db: DbContext, lexicon_id: int, user_id: int, character_id: int) -> A
.where(Membership.lexicon_id == lexicon_id) .where(Membership.lexicon_id == lexicon_id)
).scalar_one_or_none() ).scalar_one_or_none()
if not mem: if not mem:
raise ArgumentError('User is not a member of lexicon') raise ArgumentError("User is not a member of lexicon")
# If the character id is provided, check that the user owns the character # If the character id is provided, check that the user owns the character
# and the character belongs to the lexicon # and the character belongs to the lexicon
@ -36,21 +36,21 @@ def create(db: DbContext, lexicon_id: int, user_id: int, character_id: int) -> A
select(Character).where(Character.id == character_id) select(Character).where(Character.id == character_id)
).scalar_one_or_none() ).scalar_one_or_none()
if not character: if not character:
raise ArgumentError('Character does not exist') raise ArgumentError("Character does not exist")
if character.user.id != user_id: if character.user.id != user_id:
raise ArgumentError('Character is owned by the wrong player') raise ArgumentError("Character is owned by the wrong player")
if character.lexicon.id != lexicon_id: if character.lexicon.id != lexicon_id:
raise ArgumentError('Character belongs to the wrong lexicon') raise ArgumentError("Character belongs to the wrong lexicon")
signature = character.signature signature = character.signature
else: else:
signature = '~Ersatz Scrivener' signature = "~Ersatz Scrivener"
new_article = Article( new_article = Article(
lexicon_id=lexicon_id, lexicon_id=lexicon_id,
user_id=user_id, user_id=user_id,
character_id=character_id, character_id=character_id,
title='Article title', title="Article title",
body=f'\n\n{signature}', body=f"\n\n{signature}",
) )
db.session.add(new_article) db.session.add(new_article)
db.session.commit() db.session.commit()

View File

@ -16,21 +16,21 @@ 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 ArgumentError('lexicon_id') raise ArgumentError("lexicon_id")
if not isinstance(user_id, int): if not isinstance(user_id, int):
raise ArgumentError('user_id') raise ArgumentError("user_id")
if not isinstance(name, str): if not isinstance(name, str):
raise ArgumentError('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 ArgumentError('signature') raise ArgumentError("signature")
# Verify character name is valid # Verify character name is valid
if not name.strip(): if not name.strip():
raise ArgumentError('Character name cannot be blank') raise ArgumentError("Character name cannot be blank")
# If no signature is provided, use a default signature # If no signature is provided, use a default signature
if not signature or not signature.strip(): if not signature or not signature.strip():
signature = f'~{name}' signature = f"~{name}"
# 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(
@ -39,7 +39,7 @@ def create(
.where(Membership.lexicon_id == lexicon_id) .where(Membership.lexicon_id == lexicon_id)
).scalar_one_or_none() ).scalar_one_or_none()
if not mem: if not mem:
raise ArgumentError('User is not a member of lexicon') raise ArgumentError("User is not a member of lexicon")
# Check that this user is below the limit for creating characters # Check that this user is below the limit for creating characters
num_user_chars = db( num_user_chars = db(
@ -51,7 +51,7 @@ def create(
mem.lexicon.character_limit is not None mem.lexicon.character_limit is not None
and num_user_chars >= mem.lexicon.character_limit and num_user_chars >= mem.lexicon.character_limit
): ):
raise ArgumentError('User is at character limit') raise ArgumentError("User is at character limit")
new_character = Character( new_character = Character(
lexicon_id=lexicon_id, lexicon_id=lexicon_id,

View File

@ -10,7 +10,7 @@ from amanuensis.db import DbContext, Lexicon
from amanuensis.errors import ArgumentError 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-_]*$")
def create(db: DbContext, name: str, title: str, prompt: str) -> Lexicon: def create(db: DbContext, name: str, title: str, prompt: str) -> Lexicon:
@ -19,25 +19,25 @@ def create(db: DbContext, name: str, title: str, prompt: str) -> Lexicon:
""" """
# Verify name # Verify name
if not isinstance(name, str): if not isinstance(name, str):
raise ArgumentError('Lexicon name must be a string') 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):
raise ArgumentError( raise ArgumentError(
'Lexicon name may only contain alphanumerics, dash, and underscore' "Lexicon name may only contain alphanumerics, dash, and underscore"
) )
# Verify title # Verify title
if title is not None and not isinstance(name, str): if title is not None and not isinstance(name, str):
raise ArgumentError('Lexicon name must be a string') raise ArgumentError("Lexicon name must be a string")
# Verify prompt # Verify prompt
if not isinstance(prompt, str): if not isinstance(prompt, str):
raise ArgumentError('Lexicon prompt must be a string') 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:
raise ArgumentError('Lexicon name is already taken') raise ArgumentError("Lexicon name is already taken")
new_lexicon = Lexicon( new_lexicon = Lexicon(
name=name, name=name,

View File

@ -14,11 +14,11 @@ def create(db: DbContext, user_id: int, lexicon_id: int, is_editor: bool) -> Mem
""" """
# Verify argument types are correct # Verify argument types are correct
if not isinstance(user_id, int): if not isinstance(user_id, int):
raise ArgumentError('user_id') raise ArgumentError("user_id")
if not isinstance(lexicon_id, int): if not isinstance(lexicon_id, int):
raise ArgumentError('lexicon_id') raise ArgumentError("lexicon_id")
if not isinstance(is_editor, bool): if not isinstance(is_editor, bool):
raise ArgumentError('is_editor') raise ArgumentError("is_editor")
# Verify user has not already joined lexicon # Verify user has not already joined lexicon
if ( if (
@ -29,7 +29,7 @@ def create(db: DbContext, user_id: int, lexicon_id: int, is_editor: bool) -> Mem
).scalar() ).scalar()
> 0 > 0
): ):
raise ArgumentError('User is already a member of lexicon') raise ArgumentError("User is already a member of lexicon")
new_membership = Membership( new_membership = Membership(
user_id=user_id, user_id=user_id,

View File

@ -17,17 +17,17 @@ def create(db: DbContext, lexicon_id: int, user_id: int, body: str) -> Post:
# Verify lexicon id # Verify lexicon id
if not isinstance(lexicon_id, int): if not isinstance(lexicon_id, int):
raise ArgumentError('Lexicon id must be an integer.') raise ArgumentError("Lexicon id must be an integer.")
# Verify user_id # Verify user_id
if not (isinstance(user_id, int) or user_id is None): if not (isinstance(user_id, int) or user_id is None):
raise ArgumentError('User id must be an integer.') raise ArgumentError("User id must be an integer.")
# Verify body # Verify body
if not isinstance(body, str): if not isinstance(body, str):
raise ArgumentError('Post body must be a string.') 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.")
new_post = Post(lexicon_id=lexicon_id, user_id=user_id, body=body) new_post = Post(lexicon_id=lexicon_id, user_id=user_id, body=body)
db.session.add(new_post) db.session.add(new_post)

View File

@ -11,8 +11,8 @@ from amanuensis.db import DbContext, User
from amanuensis.errors import ArgumentError from amanuensis.errors import ArgumentError
RE_NO_LETTERS = re.compile(r'^[0-9-_]*$') RE_NO_LETTERS = re.compile(r"^[0-9-_]*$")
RE_ALPHANUM_DASH_UNDER = re.compile(r'^[A-Za-z0-9-_]*$') RE_ALPHANUM_DASH_UNDER = re.compile(r"^[A-Za-z0-9-_]*$")
def create( def create(
@ -28,34 +28,34 @@ def create(
""" """
# Verify username # Verify username
if not isinstance(username, str): if not isinstance(username, str):
raise ArgumentError('Username must be a string') 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):
raise ArgumentError('Username must contain a letter') raise ArgumentError("Username must contain a letter")
if not RE_ALPHANUM_DASH_UNDER.match(username): if not RE_ALPHANUM_DASH_UNDER.match(username):
raise ArgumentError( raise ArgumentError(
'Username may only contain alphanumerics, dash, and underscore' "Username may only contain alphanumerics, dash, and underscore"
) )
# Verify password # Verify password
if not isinstance(password, str): if not isinstance(password, str):
raise ArgumentError('Password must be a string') 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 ArgumentError('Display name must be a string') 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 ArgumentError('Email must be a string') 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:
raise ArgumentError('Username is already taken') raise ArgumentError("Username is already taken")
new_user = User( new_user = User(
username=username, username=username,

View File

@ -15,17 +15,17 @@ from .models import (
) )
__all__ = [ __all__ = [
'DbContext', "DbContext",
'User', "User",
'Lexicon', "Lexicon",
'Membership', "Membership",
'Character', "Character",
'ArticleState', "ArticleState",
'Article', "Article",
'IndexType', "IndexType",
'ArticleIndex', "ArticleIndex",
'ArticleIndexRule', "ArticleIndexRule",
'ArticleContentRuleType', "ArticleContentRuleType",
'ArticleContentRule', "ArticleContentRule",
'Post', "Post",
] ]

View File

@ -35,9 +35,9 @@ class Uuid(TypeDecorator):
if value is None: if value is None:
return value return value
elif not isinstance(value, uuid.UUID): elif not isinstance(value, uuid.UUID):
return f'{uuid.UUID(value).int:32x}' return f"{uuid.UUID(value).int:32x}"
else: else:
return f'{value.int:32x}' return f"{value.int:32x}"
def process_result_value(self, value, dialect): def process_result_value(self, value, dialect):
if value is None: if value is None:
@ -53,7 +53,7 @@ class User(ModelBase):
Represents a single user of Amanuensis. Represents a single user of Amanuensis.
""" """
__tablename__ = 'user' __tablename__ = "user"
############# #############
# User info # # User info #
@ -75,14 +75,14 @@ class User(ModelBase):
email = Column(String, nullable=False) email = Column(String, nullable=False)
# Whether the user can access site admin functions # Whether the user can access site admin functions
is_site_admin = Column(Boolean, nullable=False, server_default=text('FALSE')) is_site_admin = Column(Boolean, nullable=False, server_default=text("FALSE"))
#################### ####################
# History tracking # # History tracking #
#################### ####################
# The timestamp the user was created # The timestamp the user was created
created = Column(DateTime, nullable=False, server_default=text('CURRENT_TIMESTAMP')) created = Column(DateTime, nullable=False, server_default=text("CURRENT_TIMESTAMP"))
# The timestamp the user last logged in # The timestamp the user last logged in
# This is NULL if the user has never logged in # This is NULL if the user has never logged in
@ -96,10 +96,10 @@ class User(ModelBase):
# Foreign key relationships # # Foreign key relationships #
############################# #############################
memberships = relationship('Membership', back_populates='user') memberships = relationship("Membership", back_populates="user")
characters = relationship('Character', back_populates='user') characters = relationship("Character", back_populates="user")
articles = relationship('Article', back_populates='user') articles = relationship("Article", back_populates="user")
posts = relationship('Post', back_populates='user') posts = relationship("Post", back_populates="user")
class Lexicon(ModelBase): class Lexicon(ModelBase):
@ -107,7 +107,7 @@ class Lexicon(ModelBase):
Represents a single game of Lexicon. Represents a single game of Lexicon.
""" """
__tablename__ = 'lexicon' __tablename__ = "lexicon"
############# #############
# Game info # # Game info #
@ -131,11 +131,11 @@ class Lexicon(ModelBase):
#################### ####################
# The timestamp the lexicon was created # The timestamp the lexicon was created
created = Column(DateTime, nullable=False, server_default=text('CURRENT_TIMESTAMP')) created = Column(DateTime, nullable=False, server_default=text("CURRENT_TIMESTAMP"))
# The timestamp of the last change in game state # The timestamp of the last change in game state
last_updated = Column( last_updated = Column(
DateTime, nullable=False, server_default=text('CURRENT_TIMESTAMP') DateTime, nullable=False, server_default=text("CURRENT_TIMESTAMP")
) )
# The timestamp the first turn was started # The timestamp the first turn was started
@ -226,13 +226,13 @@ class Lexicon(ModelBase):
# Foreign key relationships # # Foreign key relationships #
############################# #############################
memberships = relationship('Membership', back_populates='lexicon') memberships = relationship("Membership", back_populates="lexicon")
characters = relationship('Character', back_populates='lexicon') characters = relationship("Character", back_populates="lexicon")
articles = relationship('Article', back_populates='lexicon') articles = relationship("Article", back_populates="lexicon")
indexes = relationship('ArticleIndex', back_populates='lexicon') indexes = relationship("ArticleIndex", back_populates="lexicon")
index_rules = relationship('ArticleIndexRule', back_populates='lexicon') index_rules = relationship("ArticleIndexRule", back_populates="lexicon")
content_rules = relationship('ArticleContentRule', back_populates='lexicon') content_rules = relationship("ArticleContentRule", back_populates="lexicon")
posts = relationship('Post', back_populates='lexicon') posts = relationship("Post", back_populates="lexicon")
class Membership(ModelBase): class Membership(ModelBase):
@ -240,8 +240,8 @@ class Membership(ModelBase):
Represents a user's participation in a Lexicon game. Represents a user's participation in a Lexicon game.
""" """
__tablename__ = 'membership' __tablename__ = "membership"
__table_args__ = (UniqueConstraint('user_id', 'lexicon_id'),) __table_args__ = (UniqueConstraint("user_id", "lexicon_id"),)
################### ###################
# Membership keys # # Membership keys #
@ -251,17 +251,17 @@ class Membership(ModelBase):
id = Column(Integer, primary_key=True) id = Column(Integer, primary_key=True)
# The user who is a member of a lexicon # The user who is a member of a lexicon
user_id = Column(Integer, ForeignKey('user.id'), nullable=False) user_id = Column(Integer, ForeignKey("user.id"), nullable=False)
# The lexicon of which the user is a member # The lexicon of which the user is a member
lexicon_id = Column(Integer, ForeignKey('lexicon.id'), nullable=False) lexicon_id = Column(Integer, ForeignKey("lexicon.id"), nullable=False)
#################### ####################
# History tracking # # History tracking #
#################### ####################
# Timestamp the user joined the game # Timestamp the user joined the game
joined = Column(DateTime, nullable=False, server_default=text('CURRENT_TIMESTAMP')) joined = Column(DateTime, nullable=False, server_default=text("CURRENT_TIMESTAMP"))
# Timestamp of the last time the user viewed the post feed # Timestamp of the last time the user viewed the post feed
# This is NULL if the player has never viewed posts # This is NULL if the player has never viewed posts
@ -272,7 +272,7 @@ class Membership(ModelBase):
################### ###################
# Whether the user can access editor functions # Whether the user can access editor functions
is_editor = Column(Boolean, nullable=False, server_default=text('FALSE')) is_editor = Column(Boolean, nullable=False, server_default=text("FALSE"))
######################### #########################
# Notification settings # # Notification settings #
@ -291,8 +291,8 @@ class Membership(ModelBase):
# Foreign key relationships # # Foreign key relationships #
############################# #############################
user = relationship('User', back_populates='memberships') user = relationship("User", back_populates="memberships")
lexicon = relationship('Lexicon', back_populates='memberships') lexicon = relationship("Lexicon", back_populates="memberships")
class Character(ModelBase): class Character(ModelBase):
@ -300,7 +300,7 @@ class Character(ModelBase):
Represents a character played by a uaser in a Lexicon game. Represents a character played by a uaser in a Lexicon game.
""" """
__tablename__ = 'character' __tablename__ = "character"
################## ##################
# Character info # # Character info #
@ -313,10 +313,10 @@ class Character(ModelBase):
public_id = Column(Uuid, nullable=False, unique=True, default=uuid.uuid4) public_id = Column(Uuid, nullable=False, unique=True, default=uuid.uuid4)
# The lexicon to which this character belongs # The lexicon to which this character belongs
lexicon_id = Column(Integer, ForeignKey('lexicon.id'), nullable=False) lexicon_id = Column(Integer, ForeignKey("lexicon.id"), nullable=False)
# The user to whom this character belongs # The user to whom this character belongs
user_id = Column(Integer, ForeignKey('user.id'), nullable=False) user_id = Column(Integer, ForeignKey("user.id"), nullable=False)
# The character's name # The character's name
name = Column(String, nullable=False) name = Column(String, nullable=False)
@ -328,10 +328,10 @@ class Character(ModelBase):
# Foreign key relationships # # Foreign key relationships #
############################# #############################
user = relationship('User', back_populates='characters') user = relationship("User", back_populates="characters")
lexicon = relationship('Lexicon', back_populates='characters') lexicon = relationship("Lexicon", back_populates="characters")
articles = relationship('Article', back_populates='character') articles = relationship("Article", back_populates="character")
index_rules = relationship('ArticleIndexRule', back_populates='character') index_rules = relationship("ArticleIndexRule", back_populates="character")
class ArticleState(enum.Enum): class ArticleState(enum.Enum):
@ -349,7 +349,7 @@ class Article(ModelBase):
Represents a single article in a lexicon. Represents a single article in a lexicon.
""" """
__tablename__ = 'article' __tablename__ = "article"
################ ################
# Article info # # Article info #
@ -362,17 +362,17 @@ class Article(ModelBase):
public_id = Column(Uuid, nullable=False, unique=True, default=uuid.uuid4) public_id = Column(Uuid, nullable=False, unique=True, default=uuid.uuid4)
# The lexicon to which this article belongs # The lexicon to which this article belongs
lexicon_id = Column(Integer, ForeignKey('lexicon.id'), nullable=False) lexicon_id = Column(Integer, ForeignKey("lexicon.id"), nullable=False)
# The character who is the author of this article # The character who is the author of this article
# If this is NULL, the article is written by Ersatz Scrivener # If this is NULL, the article is written by Ersatz Scrivener
character_id = Column(Integer, ForeignKey('character.id'), nullable=True) character_id = Column(Integer, ForeignKey("character.id"), nullable=True)
# The user who owns this article # The user who owns this article
user_id = Column(Integer, ForeignKey('user.id'), nullable=False) user_id = Column(Integer, ForeignKey("user.id"), nullable=False)
# The article to which this is an addendum # The article to which this is an addendum
addendum_to = Column(Integer, ForeignKey('article.id'), nullable=True) addendum_to = Column(Integer, ForeignKey("article.id"), nullable=True)
################# #################
# Article state # # Article state #
@ -394,7 +394,7 @@ class Article(ModelBase):
# Timestamp the content of the article was last updated # Timestamp the content of the article was last updated
last_updated = Column( last_updated = Column(
DateTime, nullable=False, server_default=text('CURRENT_TIMESTAMP') DateTime, nullable=False, server_default=text("CURRENT_TIMESTAMP")
) )
# Timestamp the article was last submitted # Timestamp the article was last submitted
@ -419,10 +419,10 @@ class Article(ModelBase):
# Foreign key relationships # # Foreign key relationships #
############################# #############################
lexicon = relationship('Lexicon', back_populates='articles') lexicon = relationship("Lexicon", back_populates="articles")
character = relationship('Character', back_populates='articles') character = relationship("Character", back_populates="articles")
user = relationship('User', back_populates='articles') user = relationship("User", back_populates="articles")
addenda = relationship('Article', backref=backref('parent', remote_side=[id])) addenda = relationship("Article", backref=backref("parent", remote_side=[id]))
class IndexType(enum.Enum): class IndexType(enum.Enum):
@ -441,7 +441,7 @@ class ArticleIndex(ModelBase):
Represents an index definition. Represents an index definition.
""" """
__tablename__ = 'article_index' __tablename__ = "article_index"
############## ##############
# Index info # # Index info #
@ -451,7 +451,7 @@ class ArticleIndex(ModelBase):
id = Column(Integer, primary_key=True) id = Column(Integer, primary_key=True)
# The lexicon this index is in # The lexicon this index is in
lexicon_id = Column(Integer, ForeignKey('lexicon.id'), nullable=False) lexicon_id = Column(Integer, ForeignKey("lexicon.id"), nullable=False)
# The index type # The index type
index_type = Column(Enum(IndexType), nullable=False) index_type = Column(Enum(IndexType), nullable=False)
@ -473,8 +473,8 @@ class ArticleIndex(ModelBase):
# Foreign key relationships # # Foreign key relationships #
############################# #############################
lexicon = relationship('Lexicon', back_populates='indexes') lexicon = relationship("Lexicon", back_populates="indexes")
index_rules = relationship('ArticleIndexRule', back_populates='index') index_rules = relationship("ArticleIndexRule", back_populates="index")
class ArticleIndexRule(ModelBase): class ArticleIndexRule(ModelBase):
@ -484,7 +484,7 @@ class ArticleIndexRule(ModelBase):
a rule. A character with no index rules may write in any index. a rule. A character with no index rules may write in any index.
""" """
__tablename__ = 'article_index_rule' __tablename__ = "article_index_rule"
################### ###################
# Index rule info # # Index rule info #
@ -494,17 +494,17 @@ class ArticleIndexRule(ModelBase):
id = Column(Integer, primary_key=True) id = Column(Integer, primary_key=True)
# The lexicon of this index rule # The lexicon of this index rule
lexicon_id = Column(Integer, ForeignKey('lexicon.id'), nullable=False) lexicon_id = Column(Integer, ForeignKey("lexicon.id"), nullable=False)
#################### ####################
# Index rule scope # # Index rule scope #
#################### ####################
# The character to whom this rule applies # The character to whom this rule applies
character_id = Column(Integer, ForeignKey('character.id'), nullable=False) character_id = Column(Integer, ForeignKey("character.id"), nullable=False)
# The index to which the character is restricted # The index to which the character is restricted
index_id = Column(Integer, ForeignKey('article_index.id'), nullable=False) index_id = Column(Integer, ForeignKey("article_index.id"), nullable=False)
# The turn in which this rule applies # The turn in which this rule applies
turn = Column(Integer, nullable=False) turn = Column(Integer, nullable=False)
@ -513,9 +513,9 @@ class ArticleIndexRule(ModelBase):
# Foreign key relationships # # Foreign key relationships #
############################# #############################
lexicon = relationship('Lexicon', back_populates='index_rules') lexicon = relationship("Lexicon", back_populates="index_rules")
index = relationship('ArticleIndex', back_populates='index_rules') index = relationship("ArticleIndex", back_populates="index_rules")
character = relationship('Character', back_populates='index_rules') character = relationship("Character", back_populates="index_rules")
class ArticleContentRuleType(enum.Enum): class ArticleContentRuleType(enum.Enum):
@ -557,7 +557,7 @@ class ArticleContentRule(ModelBase):
Represents a restriction on the content of an article for a turn. Represents a restriction on the content of an article for a turn.
""" """
__tablename__ = 'article_content_rule' __tablename__ = "article_content_rule"
##################### #####################
# Content rule info # # Content rule info #
@ -567,7 +567,7 @@ class ArticleContentRule(ModelBase):
id = Column(Integer, primary_key=True) id = Column(Integer, primary_key=True)
# The lexicon of this content rule # The lexicon of this content rule
lexicon_id = Column(Integer, ForeignKey('lexicon.id'), nullable=False) lexicon_id = Column(Integer, ForeignKey("lexicon.id"), nullable=False)
###################### ######################
# Content rule scope # # Content rule scope #
@ -591,7 +591,7 @@ class ArticleContentRule(ModelBase):
# Foreign key relationships # # Foreign key relationships #
############################# #############################
lexicon = relationship('Lexicon', back_populates='content_rules') lexicon = relationship("Lexicon", back_populates="content_rules")
class Post(ModelBase): class Post(ModelBase):
@ -599,7 +599,7 @@ class Post(ModelBase):
Represents a post in the game feed. Represents a post in the game feed.
""" """
__tablename__ = 'post' __tablename__ = "post"
############# #############
# Post info # # Post info #
@ -609,18 +609,18 @@ class Post(ModelBase):
id = Column(Integer, primary_key=True) id = Column(Integer, primary_key=True)
# The lexicon in which the post was made # The lexicon in which the post was made
lexicon_id = Column(Integer, ForeignKey('lexicon.id'), nullable=False) lexicon_id = Column(Integer, ForeignKey("lexicon.id"), nullable=False)
# The user who made the post # The user who made the post
# This may be NULL if the post was made by Amanuensis # This may be NULL if the post was made by Amanuensis
user_id = Column(Integer, ForeignKey('user.id'), nullable=True) user_id = Column(Integer, ForeignKey("user.id"), nullable=True)
################ ################
# Post content # # Post content #
################ ################
# The timestamp the post was created # The timestamp the post was created
created = Column(DateTime, nullable=False, server_default=text('CURRENT_TIMESTAMP')) created = Column(DateTime, nullable=False, server_default=text("CURRENT_TIMESTAMP"))
# The body of the post # The body of the post
body = Column(Text, nullable=False) body = Column(Text, nullable=False)
@ -629,5 +629,5 @@ class Post(ModelBase):
# Foreign key relationships # # Foreign key relationships #
############################# #############################
user = relationship('User', back_populates='posts') user = relationship("User", back_populates="posts")
lexicon = relationship('Lexicon', back_populates='posts') lexicon = relationship("Lexicon", back_populates="posts")

View File

@ -16,7 +16,6 @@ pytest = "^5.2"
black = "^21.5b2" black = "^21.5b2"
[tool.black] [tool.black]
skip-string-normalization = true
extend-exclude = ''' extend-exclude = '''
^/amanuensis/cli/.*| ^/amanuensis/cli/.*|
^/amanuensis/config/.*| ^/amanuensis/config/.*|

View File

@ -13,7 +13,7 @@ import amanuensis.backend.user as userq
@pytest.fixture @pytest.fixture
def db(): def db():
"""Provides an initialized database in memory.""" """Provides an initialized database in memory."""
db = DbContext('sqlite:///:memory:', debug=False) db = DbContext("sqlite:///:memory:", debug=False)
db.create_all() db.create_all()
return db return db
@ -22,15 +22,15 @@ def db():
def make_user(db: DbContext): def make_user(db: DbContext):
"""Provides a factory function for creating users, with valid default values.""" """Provides a factory function for creating users, with valid default values."""
def user_factory(state={'nonce': 1}, **kwargs): def user_factory(state={"nonce": 1}, **kwargs):
default_kwargs = { default_kwargs = {
'username': f'test_user_{state["nonce"]}', "username": f'test_user_{state["nonce"]}',
'password': 'password', "password": "password",
'display_name': None, "display_name": None,
'email': 'user@example.com', "email": "user@example.com",
'is_site_admin': False, "is_site_admin": False,
} }
state['nonce'] += 1 state["nonce"] += 1
updated_kwargs = {**default_kwargs, **kwargs} updated_kwargs = {**default_kwargs, **kwargs}
return userq.create(db, **updated_kwargs) return userq.create(db, **updated_kwargs)
@ -41,13 +41,13 @@ def make_user(db: DbContext):
def make_lexicon(db: DbContext): def make_lexicon(db: DbContext):
"""Provides a factory function for creating lexicons, with valid default values.""" """Provides a factory function for creating lexicons, with valid default values."""
def lexicon_factory(state={'nonce': 1}, **kwargs): def lexicon_factory(state={"nonce": 1}, **kwargs):
default_kwargs = { default_kwargs = {
'name': f'Test_{state["nonce"]}', "name": f'Test_{state["nonce"]}',
'title': None, "title": None,
'prompt': f'Test Lexicon game {state["nonce"]}', "prompt": f'Test Lexicon game {state["nonce"]}',
} }
state['nonce'] += 1 state["nonce"] += 1
updated_kwargs = {**default_kwargs, **kwargs} updated_kwargs = {**default_kwargs, **kwargs}
return lexiq.create(db, **updated_kwargs) return lexiq.create(db, **updated_kwargs)
@ -60,7 +60,7 @@ def make_membership(db: DbContext):
def membership_factory(**kwargs): def membership_factory(**kwargs):
default_kwargs = { default_kwargs = {
'is_editor': False, "is_editor": False,
} }
updated_kwargs = {**default_kwargs, **kwargs} updated_kwargs = {**default_kwargs, **kwargs}
return memq.create(db, **updated_kwargs) return memq.create(db, **updated_kwargs)
@ -72,12 +72,12 @@ def make_membership(db: DbContext):
def make_character(db: DbContext): def make_character(db: DbContext):
"""Provides a factory function for creating characters, with valid default values.""" """Provides a factory function for creating characters, with valid default values."""
def character_factory(state={'nonce': 1}, **kwargs): def character_factory(state={"nonce": 1}, **kwargs):
default_kwargs = { default_kwargs = {
'name': f'Character {state["nonce"]}', "name": f'Character {state["nonce"]}',
'signature': None, "signature": None,
} }
state['nonce'] += 1 state["nonce"] += 1
updated_kwargs = {**default_kwargs, **kwargs} updated_kwargs = {**default_kwargs, **kwargs}
return charq.create(db, **updated_kwargs) return charq.create(db, **updated_kwargs)

View File

@ -9,33 +9,33 @@ def test_create_character(db: DbContext, lexicon_with_editor, make):
"""Test creating a character.""" """Test creating a character."""
lexicon, user = lexicon_with_editor lexicon, user = lexicon_with_editor
kwargs = { kwargs = {
'db': db, "db": db,
'user_id': user.id, "user_id": user.id,
'lexicon_id': lexicon.id, "lexicon_id": lexicon.id,
'name': 'Character Name', "name": "Character Name",
'signature': 'Signature', "signature": "Signature",
} }
# Bad argument types # Bad argument types
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
charq.create(**{**kwargs, 'name': b'bytestring'}) charq.create(**{**kwargs, "name": b"bytestring"})
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
charq.create(**{**kwargs, 'name': None}) charq.create(**{**kwargs, "name": None})
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
charq.create(**{**kwargs, 'signature': b'bytestring'}) charq.create(**{**kwargs, "signature": b"bytestring"})
# Bad character name # Bad character name
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
charq.create(**{**kwargs, 'name': ' '}) charq.create(**{**kwargs, "name": " "})
# Signature is auto-populated # Signature is auto-populated
char = charq.create(**{**kwargs, 'signature': None}) char = charq.create(**{**kwargs, "signature": None})
assert char.signature is not None assert char.signature is not None
# User must be in lexicon # User must be in lexicon
new_user = make.user() new_user = make.user()
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
charq.create(**{**kwargs, 'user_id': new_user.id}) charq.create(**{**kwargs, "user_id": new_user.id})
def test_character_limits(db: DbContext, lexicon_with_editor): def test_character_limits(db: DbContext, lexicon_with_editor):
@ -47,31 +47,31 @@ def test_character_limits(db: DbContext, lexicon_with_editor):
# Set character limit to one and create a character # Set character limit to one and create a character
lexicon.character_limit = 1 lexicon.character_limit = 1
db.session.commit() db.session.commit()
char1 = charq.create(db, lexicon.id, user.id, 'Test Character 1', signature=None) char1 = charq.create(db, lexicon.id, user.id, "Test Character 1", signature=None)
assert char1.id, 'Failed to create character 1' assert char1.id, "Failed to create character 1"
# Creating a second character should fail # Creating a second character should fail
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
char2 = charq.create( char2 = charq.create(
db, lexicon.id, user.id, 'Test Character 2', signature=None db, lexicon.id, user.id, "Test Character 2", signature=None
) )
assert char2 assert char2
# Raising the limit to 2 should allow a second character # Raising the limit to 2 should allow a second character
lexicon.character_limit = 2 lexicon.character_limit = 2
db.session.commit() db.session.commit()
char2 = charq.create(db, lexicon.id, user.id, 'Test Character 2', signature=None) char2 = charq.create(db, lexicon.id, user.id, "Test Character 2", signature=None)
assert char2.id, 'Failed to create character 2' assert char2.id, "Failed to create character 2"
# Creating a third character should fail # Creating a third character should fail
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
char3 = charq.create( char3 = charq.create(
db, lexicon.id, user.id, 'Test Character 3', signature=None db, lexicon.id, user.id, "Test Character 3", signature=None
) )
assert char3 assert char3
# Setting the limit to null should allow a third character # Setting the limit to null should allow a third character
lexicon.character_limit = None lexicon.character_limit = None
db.session.commit() db.session.commit()
char3 = charq.create(db, lexicon.id, user.id, 'Test Character 3', signature=None) char3 = charq.create(db, lexicon.id, user.id, "Test Character 3", signature=None)
assert char3.id, 'Failed to create character 3' assert char3.id, "Failed to create character 3"

View File

@ -9,20 +9,20 @@ from amanuensis.errors import ArgumentError
def test_create_lexicon(db: DbContext): def test_create_lexicon(db: DbContext):
"""Test new game creation.""" """Test new game creation."""
kwargs = {'name': 'Test', 'title': None, 'prompt': 'A test Lexicon game'} kwargs = {"name": "Test", "title": None, "prompt": "A test Lexicon game"}
# Test name constraints # Test name constraints
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
lexiq.create(db, **{**kwargs, 'name': None}) lexiq.create(db, **{**kwargs, "name": None})
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
lexiq.create(db, **{**kwargs, 'name': ''}) lexiq.create(db, **{**kwargs, "name": ""})
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
lexiq.create(db, **{**kwargs, 'name': ' '}) lexiq.create(db, **{**kwargs, "name": " "})
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
lexiq.create(db, **{**kwargs, 'name': '..'}) lexiq.create(db, **{**kwargs, "name": ".."})
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
lexiq.create(db, **{**kwargs, 'name': '\x00'}) lexiq.create(db, **{**kwargs, "name": "\x00"})
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
lexiq.create(db, **{**kwargs, 'name': 'space in name'}) lexiq.create(db, **{**kwargs, "name": "space in name"})
# Validate that creation populates fields, including timestamps # Validate that creation populates fields, including timestamps
before = datetime.datetime.utcnow() - datetime.timedelta(seconds=1) before = datetime.datetime.utcnow() - datetime.timedelta(seconds=1)

View File

@ -11,13 +11,13 @@ def test_create_membership(db: DbContext, make):
"""Test joining a game.""" """Test joining a game."""
# Set up a user and a lexicon # Set up a user and a lexicon
new_user = make.user() new_user = make.user()
assert new_user.id, 'Failed to create user' assert new_user.id, "Failed to create user"
new_lexicon = make.lexicon() new_lexicon = make.lexicon()
assert new_lexicon.id, 'Failed to create lexicon' assert new_lexicon.id, "Failed to create lexicon"
# Add the user to the lexicon as an editor # Add the user to the lexicon as an editor
mem = memq.create(db, new_user.id, new_lexicon.id, True) mem = memq.create(db, new_user.id, new_lexicon.id, True)
assert mem, 'Failed to create membership' assert mem, "Failed to create membership"
# Check that the user and lexicon are mutually visible in the ORM relationships # Check that the user and lexicon are mutually visible in the ORM relationships
assert any(map(lambda mem: mem.lexicon == new_lexicon, new_user.memberships)) assert any(map(lambda mem: mem.lexicon == new_lexicon, new_user.memberships))

View File

@ -11,25 +11,25 @@ def test_create_post(db: DbContext, lexicon_with_editor):
lexicon, editor = lexicon_with_editor lexicon, editor = lexicon_with_editor
# argument dictionary for post object # argument dictionary for post object
kwargs = {'lexicon_id': lexicon.id, 'user_id': editor.id, 'body': 'body'} kwargs = {"lexicon_id": lexicon.id, "user_id": editor.id, "body": "body"}
# ids are integers # ids are integers
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
postq.create(db, **{**kwargs, 'user_id': 'zero'}) postq.create(db, **{**kwargs, "user_id": "zero"})
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
postq.create(db, **{**kwargs, 'lexicon_id': 'zero'}) postq.create(db, **{**kwargs, "lexicon_id": "zero"})
# empty arguments don't work # empty arguments don't work
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
postq.create(db, **{**kwargs, 'lexicon_id': ''}) postq.create(db, **{**kwargs, "lexicon_id": ""})
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
postq.create(db, **{**kwargs, 'user_id': ''}) postq.create(db, **{**kwargs, "user_id": ""})
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
postq.create(db, **{**kwargs, 'body': ''}) postq.create(db, **{**kwargs, "body": ""})
# post with only whitespace doesn't work # post with only whitespace doesn't work
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
postq.create(db, **{**kwargs, 'body': ' '}) postq.create(db, **{**kwargs, "body": " "})
# post creation works and populates fields # post creation works and populates fields
new_post = postq.create(db, **kwargs) new_post = postq.create(db, **kwargs)
@ -39,6 +39,6 @@ def test_create_post(db: DbContext, lexicon_with_editor):
assert new_post.body is not None assert new_post.body is not None
# post creation works when user is None # post creation works when user is None
new_post = postq.create(db, **{**kwargs, 'user_id': None}) new_post = postq.create(db, **{**kwargs, "user_id": None})
assert new_post assert new_post
assert new_post.user_id is None assert new_post.user_id is None

View File

@ -8,26 +8,26 @@ from amanuensis.errors import ArgumentError
def test_create_user(db: DbContext): def test_create_user(db: DbContext):
"""Test new user creation.""" """Test new user creation."""
kwargs = { kwargs = {
'username': 'username', "username": "username",
'password': 'password', "password": "password",
'display_name': 'User Name', "display_name": "User Name",
'email': 'user@example.com', "email": "user@example.com",
'is_site_admin': False, "is_site_admin": False,
} }
# Test length constraints # Test length constraints
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
userq.create(db, **{**kwargs, 'username': 'me'}) userq.create(db, **{**kwargs, "username": "me"})
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
userq.create( userq.create(
db, **{**kwargs, 'username': 'the right honorable user-name, esquire'} db, **{**kwargs, "username": "the right honorable user-name, esquire"}
) )
# Test allowed characters # Test allowed characters
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
userq.create(db, **{**kwargs, 'username': 'user name'}) userq.create(db, **{**kwargs, "username": "user name"})
# No password # No password
with pytest.raises(ArgumentError): with pytest.raises(ArgumentError):
userq.create(db, **{**kwargs, 'password': None}) userq.create(db, **{**kwargs, "password": None})
# Valid creation works and populates fields # Valid creation works and populates fields
new_user = userq.create(db, **kwargs) new_user = userq.create(db, **kwargs)
@ -40,6 +40,6 @@ def test_create_user(db: DbContext):
duplicate = userq.create(db, **kwargs) duplicate = userq.create(db, **kwargs)
# Missing display name populates with username # Missing display name populates with username
user2_kw = {**kwargs, 'username': 'user2', 'display_name': None} user2_kw = {**kwargs, "username": "user2", "display_name": None}
user2 = userq.create(db, **user2_kw) user2 = userq.create(db, **user2_kw)
assert user2.display_name is not None assert user2.display_name is not None