Key files

What each file in a feature does, with real code from the codebase.

Table of contents

__init__.py

The entry point. Defines the blueprint, registers services, provides framework hooks:

# splent_feature_auth/__init__.py
from splent_framework.blueprints.base_blueprint import create_blueprint
from splent_framework.services.service_locator import register_service
from splent_io.splent_feature_auth.services import AuthenticationService

auth_bp = create_blueprint(__name__)

def init_feature(app):
    register_service(app, "AuthenticationService", AuthenticationService)

def inject_context_vars(app):
    return {}

config.py

Injects environment variables into app.config. This is how the framework tracks env vars and how refinement features (like mailhog overriding mail’s SMTP) work:

import os

def inject_config(app):
    app.config.update({
        "MAIL_SERVER": os.getenv("MAIL_SERVER", "smtp.example.com"),
        "MAIL_PORT": int(os.getenv("MAIL_PORT", "587")),
    })

Without config.py, env vars used via os.getenv() are invisible to the framework. Use feature:inject-config to auto-generate it.


models.py

SQLAlchemy models. Each model is self-contained — it must not import models from other features:

from splent_framework.db import db

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(256), unique=True)
    password = db.Column(db.String(256), nullable=False)
    active = db.Column(db.Boolean, default=True)

If profile => auth in UVL, then profile may import from auth, but auth must never import from profile.


services.py

Business logic. Extends BaseService. Can emit signals for cross-feature communication:

from splent_framework.services.BaseService import BaseService

class AuthenticationService(BaseService):
    def __init__(self):
        super().__init__(UserRepository())

    def login(self, email, password, remember=True):
        user = self.repository.get_by_email(email)
        if user and user.check_password(password):
            login_user(user, remember=remember)
            return True
        return False

See Services for the full pattern.


repositories.py

Data access layer. One repository per model:

from splent_framework.repositories.BaseRepository import BaseRepository
from splent_io.splent_feature_auth.models import User

class UserRepository(BaseRepository):
    def __init__(self):
        super().__init__(User)

    def get_by_email(self, email, active=True):
        return self.model.query.filter_by(email=email, active=active).first()

See Repositories for the full pattern.


routes.py

Flask routes. Handle HTTP only — delegate logic to services:

from splent_io.splent_feature_auth import auth_bp
from splent_framework.services.service_locator import service_proxy

auth_service = service_proxy("AuthenticationService")

@auth_bp.route("/login", methods=["GET", "POST"])
def login():
    ...

hooks.py

Registers template hooks — named slots where this feature injects HTML:

from splent_framework.hooks.template_hooks import register_template_hook
from flask import render_template

def sidebar_items():
    return render_template("hooks/sidebar_items.html")

register_template_hook("layout.sidebar", sidebar_items)

See Template hooks.


commands.py

CLI commands exposed as splent feature:<name> <command>:

import click

@click.command("test")
@click.option("--to", required=True, metavar="EMAIL")
def mail_test(to):
    """Send a test email."""
    ...

cli_commands = [mail_test]

signals.py

Listens to signals from upstream features:

from splent_io.splent_feature_auth.signals import user_registered

@user_registered.connect
def on_user_registered(sender, **kwargs):
    user = kwargs["user"]
    # Create default profile

Must be imported in __init__.py to register handlers.


decorators.py

Feature-specific decorators that other features import:

from flask_login import login_required  # noqa: F401
# Other features: from splent_io.splent_feature_auth.decorators import login_required

Makes the dependency explicit for product:validate.


seeders.py

Database seeder for development/test data:

from splent_framework.seeders.BaseSeeder import BaseSeeder
from splent_io.splent_feature_auth.models import User

class AuthSeeder(BaseSeeder):
    def run(self):
        self.seed([User(email="admin@example.com", password="1234")])

See Seeders.


migrations/

Per-feature Alembic migrations. Each feature has its own alembic_<feature> version table. Generated with splent db:migrate, applied with splent db:upgrade.


See also


Back to top

splent. Distributed by an LGPL license v3. Contact us: drorganvidez@us.es