SPLENT Framework

Table of contents

  1. Introduction
  2. How the pieces fit
  3. What a feature gives the framework
  4. Finding what you need
  5. Reference
    1. Package layout
  6. See also

Introduction

splent_framework is the library every SPLENT product runs on. It builds one Flask app out of your product’s features, and gives those features what every web app needs, such as configuration, a database, templates, menus, storage and background tasks. Read this section when you write a feature, or when you want to know what your app does as it starts.

Your product’s code to start the app is one call.

from splent_framework.app_factory import create_splent_app


def create_app(config_name=None):
    return create_splent_app(__name__, config_name)

How the pieces fit

How a product, the framework and its features fit together PRODUCT create_app() its only code is a call to create_splent_app FRAMEWORK, ONE PIPELINE config, proxies, security database, logging, errors locale, Jinja, CSRF FeatureManager storage, sessions, probes 25 steps, fixed order FEATURES Each declared feature in UVL order, refiners after bases inject_config, init_feature blueprints, models, hooks fill REGISTRIES template hooks signals services nav items assets settings search file access admin resources menus
The product hands its app to the framework's pipeline. One step loads the features, which register what they offer in the framework's registries.

The factory runs the same 25 steps in every product. One of them loads your features in the order of the UVL model. Each feature registers what it offers, such as services, hooks, menu entries and assets, and the rest of the app reads it from there.


What a feature gives the framework

from splent_framework.blueprints.base_blueprint import create_blueprint

notes_bp = create_blueprint(__name__)


def init_feature(app):
    ...

A feature brings a blueprint and, when it needs them, inject_config(app) in its config.py, init_feature(app) and inject_context_vars(app). The framework calls each at the right moment. What a feature gives the framework has the full list.


Finding what you need

You want to Read
Know what happens when the app starts, or change an error page Application initialization
Set or read a setting Configuration
Know in which order features load, or why one did not Feature loading
Write a blueprint, a service, a repository or a seeder Architecture layers
Define models and migrate them Database
Add to another feature’s page, or pass variables to templates Template system
React to what another feature does Signals
Style the public site with a theme or a skin Theme system
Translate your feature Internationalization (i18n)
Open a screen to some roles only Access control
Add an entry to a menu, or a page to a shell Menus and shells
Record who did what, or report a degraded service Audit and reports
Run work outside the request Background tasks
Keep files Storage
Serve an HTTP API HTTP APIs
Limit how often a form is sent Rate limits and forms
Read the site’s name, time zone or address The site
Give items a slug, preview drafts, page lists, fill the sitemap Content helpers
Keep a value that is slow to make Cache
Fetch an address a user typed Fetching URLs
Make your feature’s content searchable Search
Test your feature with the framework’s fixtures Testing the framework

Reference

Package layout

Each startup step belongs to one manager in managers/, which runs once, at start. The other packages are what features call while they run.

splent_framework/
├── app_factory.py                 create_splent_app, _PIPELINE
├── db.py                          SQLAlchemy singleton (db)
├── optional.py                    optional_module, optional_attr
├── managers/
│   ├── config_manager.py          ConfigManager, resolve_config_name
│   ├── migration_manager.py       MigrationManager
│   ├── feature_manager.py         FeatureManager
│   ├── feature_loader.py          FeatureLoader + collaborators
│   ├── feature_order.py           FeatureLoadOrderResolver
│   ├── namespace_manager.py       NamespaceManager
│   ├── session_manager.py         SessionManager
│   ├── jinja_manager.py           JinjaManager
│   ├── error_handler_manager.py   ErrorHandlerManager
│   ├── locale_manager.py          LocaleManager
│   ├── logging_manager.py         LoggingManager
│   ├── proxy_manager.py           ProxyManager
│   ├── security_headers_manager.py SecurityHeadersManager, csp_nonce
│   ├── cookie_security_manager.py CookieSecurityManager
│   ├── csp.py                     the Content-Security-Policy of each page
│   ├── static_cache_manager.py    StaticCacheManager
│   ├── task_manager.py            TaskManager (checks TASKS_MODE at start)
│   ├── health_manager.py          HealthManager, the /healthz and /readyz probes
│   ├── csrf_manager.py            CSRFManager
│   ├── mapper_guard.py            models of features the app does not load
│   └── db_manager.py              MigrateManager, an alias of MigrationManager
├── blueprints/
│   └── base_blueprint.py          create_blueprint, BaseBlueprint
├── repositories/
│   └── BaseRepository.py          BaseRepository[T]
├── services/
│   ├── BaseService.py             BaseService
│   ├── service_locator.py         register_service, get_service_class, service_proxy
│   └── file_access.py             register_file_access_resolver, resolve_file_access, send_protected_file
├── seeders/
│   └── BaseSeeder.py              BaseSeeder, SeederError
├── hooks/
│   └── template_hooks.py          Template hook registry
├── signals/
│   ├── registry.py                Signal registry (register_signal, get_registry)
│   └── signal_utils.py            define_signal, connect_signal
├── refinement/
│   ├── __init__.py                refine_model, refine_service
│   ├── parser.py                  parse_extensible, parse_refinement
│   ├── validator.py               validate_refinements
│   ├── conflicts.py               find_conflicts, RefinerFacts, BaseFacts, Conflict
│   ├── facts.py                   collect_runtime_facts (boot conflict check)
│   ├── templates.py               loader for declared template overrides
│   ├── registry.py                RefinementRegistry, RefinementEntry
│   └── model_extender.py          apply_model_mixin
├── admin/
│   └── registry.py                register_admin_resource, AdminResource
├── audit/
│   └── __init__.py                record_event, register_audit_recorder
├── observability/
│   └── __init__.py                report_degraded, register_degradation_reporter, request_id
├── health/
│   └── __init__.py                register_readiness_check, register_readiness_listener
├── tasks/
│   ├── registry.py                task, TaskSpec
│   ├── dispatch.py                enqueue, get_run, wait, TaskSettings
│   ├── runs.py                    TaskRun, its statuses, report_progress, reporting
│   ├── backends.py                the sync, thread and rq executors
│   └── worker.py                  python -m splent_framework.tasks.worker
├── storage/
│   └── __init__.py                feature_storage, register_storage_move, /files/<feature>/...
├── cache/
│   └── __init__.py                feature_cache
├── fetch/
│   └── __init__.py                fetch, Fetched, FetchError
├── api/
│   └── __init__.py                Problem, paginate, page_answer, conditional, accepted, deprecate
├── ratelimit/
│   └── __init__.py                SharedThrottle, rate_limited, use_table, client_ip
├── guard/
│   └── __init__.py                form_guard, Refused
├── keys/
│   └── __init__.py                purpose_key, serializer, KeyRing (SPLENT_DERIVED_KEYS)
├── params/
│   ├── schema.py                  [tool.splent.config_schema]: parse_schema, Param, breaking_changes
│   └── runtime.py                 param, the parameters of the loaded features
├── settings/
│   └── settings_schema.py         register_settings, get_config, setting_value
├── nav/
│   ├── nav_registry.py            register_nav_item, get_nav_items
│   └── menu_registry.py           register_menu_item, register_user_menu_item, menu_sections
├── layout/
│   └── shells.py                  shell (the layout a page extends, by shell)
├── search/
│   ├── search_registry.py         register_search_source, register_search_field, resolve_search_hits
│   └── schema.py                  text, keyword, nested..., register_search_facet, register_search_sort
├── ui/
│   ├── __init__.py                the page script in layout.scripts
│   └── static/splent-ui.js        data-confirm, data-copy, data-reveal, data-busy, SPLENT.fetch/json/notify
├── site/
│   └── __init__.py                site_name, site_timezone, local_now, local_today
├── urls/
│   └── __init__.py                site_root, external_url_for, has_endpoint, safe_next_url
├── roles/
│   └── __init__.py                PANEL_ROLES, ADMIN_ROLES
├── content/
│   └── __init__.py                unique_slug, public_or_preview
├── pages/
│   └── __init__.py                page_of, pager
├── sitemap/
│   └── __init__.py                register_sitemap, /sitemap.xml
├── assets/
│   └── asset_registry.py          register_asset, get_assets (per shell)
├── i18n/
│   └── text.py                    localized, parse_localized
├── context/
│   └── context_manager.py         Jinja context builder
├── decorators/
│   └── decorators.py              role_required, has_role, register_access_policy
├── markdown/
│   └── render.py                  render_markdown
├── rich_text/
│   └── sanitize.py                sanitize_html (the rich_text filter)
├── dates/
│   └── __init__.py                the date, datetime and time_tag filters
├── sizes/
│   └── __init__.py                the filesize filter
├── empty/
│   └── __init__.py                empty_state
├── icons/
│   └── __init__.py                icon, register_icon_set
├── migrations/
│   └── feature_env.py             run_feature_migrations (called from every feature's env.py)
├── utils/
│   ├── path_utils.py              PathUtils, protected_uploads_dir
│   ├── pyproject_reader.py        PyprojectReader
│   ├── feature_utils.py           get_features_from_pyproject
│   ├── form_helpers.py            form_success, form_error, form_int
│   ├── app_loader.py              get_create_app_in_testing_mode
│   ├── text.py                    slugify, summary (the summary filter)
│   └── uvl_resolver.py            resolve_product_uvl (finds the SPL model on disk)
├── translations/                  the framework's own catalog (es), for the pages it draws
├── configuration/
│   ├── default_config.py          Config / DevelopmentConfig / ..., operator_settings
│   ├── layers.py                  the trace product:config shows, key by key
│   └── configuration.py           uploads_folder_name, get_app_version, is_production
├── environment/
│   └── host.py                    get_host_for_testing and friends
├── fixtures/
│   └── fixtures.py                pytest fixtures
├── helpers/
│   └── test_helpers_auth.py       login, logout test helpers
├── bootstraps/
│   └── locustfile_bootstrap.py    discover_locustfiles, load_locustfiles
├── locust/
│   └── common.py                  get_csrf_token
└── selenium/
    └── common.py                  initialize_driver, close_driver

See also


Table of contents


Back to top

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