Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[proofing] Add pagination for revision list #485

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ devserver: py-venv-check

# Run a local Celery instance for background tasks.
celery:
celery -A ambuda.tasks worker --loglevel=INFO
celery -A make_celery worker --loglevel=INFO


# Docker commands
Expand Down
55 changes: 20 additions & 35 deletions ambuda/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@
from flask import Flask, session
from flask_babel import Babel, pgettext
from sentry_sdk.integrations.flask import FlaskIntegration
from sqlalchemy import exc

import config
from ambuda import admin as admin_manager
from ambuda import auth as auth_manager
from ambuda import checks, filters, queries
from ambuda import checks, filters
from ambuda.consts import LOCALES
from ambuda.mail import mailer
from ambuda.models.base import db
from ambuda.tasks import celery_init_app
from ambuda.utils import assets
from ambuda.utils.json_serde import AmbudaJSONEncoder
from ambuda.utils.url_converters import ListConverter
from ambuda.views.about import bp as about
from ambuda.views.api import bp as api
Expand All @@ -42,32 +42,6 @@ def _initialize_sentry(sentry_dsn: str):
)


def _initialize_db_session(app, config_name: str):
"""Ensure that our SQLAlchemy session behaves well.

The Flask-SQLAlchemy library manages all of this boilerplate for us
automatically, but Flask-SQLAlchemy has relatively poor support for using
our models outside of the application context, e.g. when running seed
scripts or other batch jobs. So instead of using that extension, we manage
the boilerplate ourselves.
"""

@app.teardown_appcontext
def shutdown_session(exception=None):
"""Reset session state to prevent caching and memory leaks."""
queries.get_session_class().remove()

if config_name == config.PRODUCTION:
# The hook below hides database errors. So, install the hook only if
# we're in production.

@app.errorhandler(exc.SQLAlchemyError)
def handle_db_exceptions(error):
"""Rollback errors so that the db can handle future requests."""
session = queries.get_session()
session.rollback()


def _initialize_logger(log_level: int) -> None:
"""Initialize a simple logger for all requests."""
handler = logging.StreamHandler(sys.stderr)
Expand All @@ -79,7 +53,11 @@ def _initialize_logger(log_level: int) -> None:


def create_app(config_env: str):
"""Initialize the Ambuda application."""
"""Initialize the Ambuda application.

:param config_env: the config environment to use. For valid values, see
the string constants in `config.py`.
"""

# We store all env variables in a `.env` file so that it's easier to manage
# different configurations.
Expand All @@ -99,6 +77,12 @@ def create_app(config_env: str):
# Config
app.config.from_object(config_spec)

# Database
db.init_app(app)

# Celery
celery_init_app(app)

# Sanity checks
assert config_env == config_spec.AMBUDA_ENVIRONMENT
if config_env != config.TESTING:
Expand All @@ -108,10 +92,7 @@ def create_app(config_env: str):
# Logger
_initialize_logger(config_spec.LOG_LEVEL)

# Database
_initialize_db_session(app, config_env)

# Extensions
# Various Flask extensions
babel = Babel(app)

@babel.localeselector
Expand Down Expand Up @@ -142,12 +123,17 @@ def get_locale():

# Debug-only routes for local development.
if app.debug:
from flask_debugtoolbar import DebugToolbarExtension

from ambuda.views.debug import bp as debug_bp

DebugToolbarExtension(app)
app.register_blueprint(debug_bp, url_prefix="/debug")

# i18n string trimming
# For more, see:https://jinja.palletsprojects.com/en/3.1.x/api/#ext-i18n-trimmed
app.jinja_env.policies["ext.i18n.trimmed"] = True

# Template functions and filters
app.jinja_env.filters.update(
{
Expand All @@ -167,5 +153,4 @@ def get_locale():
}
)

app.json_encoder = AmbudaJSONEncoder
return app
4 changes: 2 additions & 2 deletions ambuda/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from flask_login import current_user

import ambuda.database as db
import ambuda.queries as q
from ambuda.models.base import db as flask_sqla


class AmbudaIndexView(AdminIndexView):
Expand Down Expand Up @@ -68,7 +68,7 @@ class SponsorshipView(ModeratorBaseView):


def create_admin_manager(app):
session = q.get_session_class()
session = flask_sqla.session
admin = Admin(
app,
name="Ambuda",
Expand Down
4 changes: 2 additions & 2 deletions ambuda/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from ambuda import consts, enums
from ambuda import database as db
from ambuda import queries as q
from ambuda.models.base import Base
from ambuda.models.base import db as flask_sqla


def _warn(text: str = ""):
Expand Down Expand Up @@ -70,7 +70,7 @@ def _check_app_schema_matches_db_schema(database_uri: str) -> list[str]:

errors = []

for table_name, table in Base.metadata.tables.items():
for table_name, table in flask_sqla.Model.metadata.tables.items():
app_columns = table.columns
db_columns = {c["name"]: c for c in inspector.get_columns(table_name)}

Expand Down
1 change: 0 additions & 1 deletion ambuda/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from ambuda.enums import SiteRole # NOQA F401
from ambuda.models.auth import * # NOQA F401,F403
from ambuda.models.base import Base # NOQA F401,F403
from ambuda.models.blog import * # NOQA F401,F403
from ambuda.models.dictionaries import * # NOQA F401,F403
from ambuda.models.parse import * # NOQA F401,F403
Expand Down
10 changes: 5 additions & 5 deletions ambuda/models/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
from sqlalchemy.orm import relationship
from werkzeug.security import check_password_hash, generate_password_hash

from ambuda.models.base import Base, foreign_key, pk
from ambuda.models.base import db, foreign_key, pk
from ambuda.utils.user_mixins import AmbudaUserMixin


class User(AmbudaUserMixin, Base):
class User(AmbudaUserMixin, db.Model):
akprasad marked this conversation as resolved.
Show resolved Hide resolved
"""A user."""

__tablename__ = "users"
Expand Down Expand Up @@ -63,7 +63,7 @@ def check_password(self, raw_password: str) -> bool:
return check_password_hash(self.password_hash, raw_password)


class Role(Base):
class Role(db.Model):

"""A role.

Expand All @@ -83,7 +83,7 @@ def __repr__(self):
return f"<Role({self.id}, {self.name!r})>"


class UserRoles(Base):
class UserRoles(db.Model):

"""Secondary table for users and roles."""

Expand All @@ -95,7 +95,7 @@ class UserRoles(Base):
role_id = Column(Integer, ForeignKey("roles.id"), primary_key=True, index=True)


class PasswordResetToken(Base):
class PasswordResetToken(db.Model):

"""Models a "forgot password" recovery token."""

Expand Down
8 changes: 4 additions & 4 deletions ambuda/models/base.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"""Base model and utilities."""

from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Column, ForeignKey, Integer
from sqlalchemy.orm import declarative_base

#: The base class for all of Ambuda's models. All new models should inherit
#: from this class.
Base = declarative_base()
# TODO(arun): rename and standardize this across the project. Avoid confusion
# with the `database` module, which is usually imported as `db`.
db = SQLAlchemy(session_options=dict(autoflush=False, autocommit=False))


def pk():
Expand Down
4 changes: 2 additions & 2 deletions ambuda/models/blog.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
from sqlalchemy import Text as Text_
from sqlalchemy.orm import relationship

from ambuda.models.base import Base, foreign_key, pk, same_as
from ambuda.models.base import db, foreign_key, pk, same_as


class BlogPost(Base):
class BlogPost(db.Model):

"""A blog post."""

Expand Down
6 changes: 3 additions & 3 deletions ambuda/models/dictionaries.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from sqlalchemy import Column, String
from sqlalchemy.orm import relationship

from ambuda.models.base import Base, foreign_key, pk
from ambuda.models.base import db, foreign_key, pk


class Dictionary(Base):
class Dictionary(db.Model):

"""A dictionary that maps Sanskrit expressions to definitions in
various languages."""
Expand All @@ -21,7 +21,7 @@ class Dictionary(Base):
entries = relationship("DictionaryEntry", backref="dictionary", cascade="delete")


class DictionaryEntry(Base):
class DictionaryEntry(db.Model):

"""Dictionary definitions for a specific entry key.

Expand Down
4 changes: 2 additions & 2 deletions ambuda/models/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
from sqlalchemy import Column
from sqlalchemy import Text as _Text

from ambuda.models.base import Base, foreign_key, pk
from ambuda.models.base import db, foreign_key, pk


class BlockParse(Base):
class BlockParse(db.Model):
"""Parse data for a `TextBlock`."""

__tablename__ = "block_parses"
Expand Down
10 changes: 5 additions & 5 deletions ambuda/models/proofing.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from sqlalchemy import Text as Text_
from sqlalchemy.orm import relationship

from ambuda.models.base import Base, foreign_key, pk, same_as
from ambuda.models.base import db, foreign_key, pk, same_as


def string():
Expand All @@ -19,7 +19,7 @@ def text():
return Column(Text_, nullable=False, default="")


class Project(Base):
class Project(db.Model):

"""A proofreading project.

Expand Down Expand Up @@ -69,7 +69,7 @@ class Project(Base):
)


class Page(Base):
class Page(db.Model):

"""A page in a proofreading project.

Expand Down Expand Up @@ -115,7 +115,7 @@ class Page(Base):
)


class PageStatus(Base):
class PageStatus(db.Model):

"""The transcription status of a given page.

Expand All @@ -130,7 +130,7 @@ class PageStatus(Base):
name = Column(String, nullable=False, unique=True)


class Revision(Base):
class Revision(db.Model):

"""A specific page revision.

Expand Down
4 changes: 2 additions & 2 deletions ambuda/models/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
from sqlalchemy import Column, Integer, String
from sqlalchemy import Text as Text_

from ambuda.models.base import Base, pk
from ambuda.models.base import db, pk


class ProjectSponsorship(Base):
class ProjectSponsorship(db.Model):

"""A project that a donor can sponsor."""

Expand Down
8 changes: 4 additions & 4 deletions ambuda/models/talk.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
from sqlalchemy import Text as Text_
from sqlalchemy.orm import relationship

from ambuda.models.base import Base, foreign_key, pk, same_as
from ambuda.models.base import db, foreign_key, pk, same_as


def string():
"""Create a non-nullable string column that defaults to the empty string."""
return Column(String, nullable=False, default="")


class Board(Base):
class Board(db.Model):

"""A list of threads."""

Expand All @@ -34,7 +34,7 @@ class Board(Base):
)


class Thread(Base):
class Thread(db.Model):

"""A list of posts."""

Expand All @@ -59,7 +59,7 @@ class Thread(Base):
posts = relationship("Post", order_by=lambda: Post.created_at, backref="thread")


class Post(Base):
class Post(db.Model):

"""A post."""

Expand Down
8 changes: 4 additions & 4 deletions ambuda/models/texts.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
from sqlalchemy import Text as _Text
from sqlalchemy.orm import relationship

from ambuda.models.base import Base, foreign_key, pk
from ambuda.models.base import db, foreign_key, pk


class Text(Base):
class Text(db.Model):

"""A text with its metadata."""

Expand All @@ -32,7 +32,7 @@ class Text(Base):
sections = relationship("TextSection", backref="text", cascade="delete")


class TextSection(Base):
class TextSection(db.Model):

"""Ordered divisions of text content. This represent divisions like kāṇḍas,
sargas, etc.
Expand Down Expand Up @@ -63,7 +63,7 @@ class TextSection(Base):
)


class TextBlock(Base):
class TextBlock(db.Model):
"""A verse or paragraph.

A TextBlock is the "unit of reuse." When we make cross-references between
Expand Down
Loading