-
Notifications
You must be signed in to change notification settings - Fork 86
Architecture
As I don't know if anyone will ever read this, I'll keep this very high level for now, where I feel it's necessary.
lute is the app module. Each subfolder under it is either a blueprint or a utility/service package:
-
backup: the/backuproutes and service -
bing: the/bingroutes and service ... etc
Special things:
-
db: database setup and migrations, and demo data management -
dev_api: special/dangerous routes used during testing only (not loaded if app ENV = prod) -
models: the Sqlalchemy models -
parse: parsing -
utils: utils
The classes in lute.models are Sqlalchemy classes. Most of these have simple methods for things like finding, loading, etc.
Some DB models (e.g. lute.models.language.Language) are used throughout the application, as they're pretty much just data classes with little functionality.
There are two more useful domain models:
lute.term.model.Termlute.book.model.Book
These are used more frequently in the code as they provide useful domain-level abstractions. They both have corresponding lute.X.model.Repository objects that translate these models to and from the DB/Sqlalchemy models.
Lute shows some data as tabular data in datatables, which just use Sqlalchemy to query the db directly without models. The lute.utils.data_tables module helps with that.
Except for parsing and rendering, the model for Lute is pretty simple:
- a route in a blueprint's
routesmodule receives an incoming requests - the route delegates to some kind of
servicemodule in the blueprint - the
servicedeals with either DB or domain models as needed, and commits to thelute.dbvia usual Flask-Sqlalchemy methods.
- The user studies
lute.models.language.Language - The user creates
lute.book.model.Book(domain object), which is saved as alute.models.Bookdb object. ADbBookhas one or morelute.models.book.Textobjects, which are the pages in theBook. - The user reads the text in the
lute.readroutes, and createslute.term.model.Termobjects, which are saved in the database aslute.models.term.Termobjects.
- The main entry point is
lute.mainwhich initializes the db and app. -
lute.maincallslute.config.app_config.AppConfigto get the configuration from thelute/config/config.yml. The config.yml file is pre-written for Docker, or the prod example is used.AppConfigis used in several places in the code to re-read the config file. Among other things, the config gives the name of the folder where the user's data will be stored; this is suppliedy by the libraryPlatformDirsif it's not configured. -
lute.maincallslute.app_setup, the app factory.app_setup:- calls
lute.db.setup.mainto run db migrations and backups as needed. Migrations are handled bylute.db.setup.migrator, using files inlute/db/schema/. - loads all of the blueprints into the app.
- calls
-
lute.mainhands the configured app off to waitress.
- Parsers are defined in
lute.parse, with a baseAbstractParsersubclassed by other parsers. The parsers are loaded into alute.parse.registrywhich is consulted at runtime to determine which parsers are supported in the current environment. - Any time a page is requested or a new
Termis created, the appropriate parser is found from theparse.registry. The parser uses theLanguageto get a list ofParsedTokens. - If rendering, the list of
ParsedTokensis given to thelute.read.render.renderable_calculatorto determine which tokens, and which parts of tokens, should actually be rendered. - When rendered, the
lute/static/js/lute.jsfile adds javascript event handlers for each of the word elements in the rendered HTML. These handlers get/post back to various bluescript routes.
This wiki is for developer documentation. User documentation is in the user manual
Thanks!