- Python 99.3%
- Makefile 0.7%
| .vscode | ||
| borgdrone | ||
| files | ||
| tests | ||
| .gitignore | ||
| Makefile | ||
| poetry.lock | ||
| poetry.toml | ||
| pyproject.toml | ||
| README.md | ||
| ruff.toml | ||
Development
Requirements
Manjaro Linux
pamac install \
python-poetry \
python-poetry-dynamic-versioning \
pnpm \
dart-sass
poetry config virtualenvs.in-project true
Standards
views: - no direct logging, ResponseHelper() and SomeManager() only - No direct calls to any manager other than those owned by the module
Module.ObjectManager
- may log with
logger.debug("", color="") - other than database queries, all functions must return
BorgwebEvent[Object]()- use
return_success(),return_error(),return_debug_success(),return_debug_error()only
- use
- In the event that the function returns any result from
BorgRunner, it need's itseventattribute changed must be returned to the view.- Comments should be used to indicate possible errors from
BorgRunner.
- Comments should be used to indicate possible errors from
- Error handling for
BorgRunnershould be done here, not inBorgRunner.
Module.models
__tablename__is not required in flask_sqlalchemy but I like setting it explicitly- Map types when possible
BorgdroneEvent
Error checking
result_log = BorgRunner.repository_info(path, passphrase)
if result_log.status == "FAILURE":
return result_log.return_failure()
FlaskHelper
This is a complicated helper class I will admit, but it solves alot of problems using htmx causes, and greatly simplifies the process of forming Response objects.
Templates Hierachy
<!-- templates/base.html -->
<body>
...
<div id="content-1" class="flex-grow-1"></div>
...
</body>
<!-- module/templates/module/index.html -->
{% include 'module/header.html' %}
<div id="content-2" class="content-2">{% include 'module/....html' %}</div>
<!-- module/templates/module/some_file.html -->
<form hx-target="#content-2" hx-post="{{ url_for('...') }}"></form>
Template flow:
sidebar.htmllinks insert modules'index.htmlinto#content-1index.htmls includeheader.htmland define#content-2#content-2is the target for all pages in the module
Fragment Redirects
These are NOT true 30X redirects. These methods solve the issue caused by using jinja includes.
respond_htmx_location()
This uses the "HX-Location" header.
# Sender
def create_repo() -> Response:
...
if request.method == "POST":
result_log = ...
if result_log.status == "FAILURE":
return rh.respond_htmx_location("repositories.create_repo")
# Target
def index() -> Response:
repos = database.get_all_by_kwargs....
rh.context_data["repositories"] = repos
rh.template_fragment = "repositories/repositories.html"
return rh.respond_get("repositories/index.html")
This will redirect the user to the target page, but not perform a client reload. The benefit of this method, is that index pages contain multiple includes, and usually requre context.
If in "sender" we replace respond_htmx_location with
respond_get we'd have to provide template name, and get the repos as context data, which is
redundant. and if either of those things change, we'd have to change it in both places.
Also, index.htmls contain includes we do not want to duplicate. Most <form> targets are #content-2, so
everything outside that div in the index (like headers and footers) will be duplicated. Bad.
The limitation oif this method is that ResponeHelper().htmx_refresh will not work. So things like, the sidebar, will not update.
respond_htmx_location_and_refresh()
This uses the "HX-Redirect" header.
def logout():
...
return rh.respond_htmx_location_and_refresh("dashboard.index")
This will also prevent duplication of content, but will perform a full client reload allowing
any jinja logic to be re-evaluated like {% if current_user.is_authenticated %}