No description
  • Python 99.3%
  • Makefile 0.7%
Find a file
2025-07-31 21:02:18 -04:00
.vscode update some preferences 2025-07-28 15:00:10 -04:00
borgdrone bump 2025-07-31 21:02:18 -04:00
files add a file 2025-07-31 20:10:02 -04:00
tests complete reset 2025-07-28 13:36:09 -04:00
.gitignore ignore system configs 2025-07-31 20:10:27 -04:00
Makefile suppress command output 2025-07-31 20:06:56 -04:00
poetry.lock add disto dep 2025-07-31 20:06:35 -04:00
poetry.toml Init 2024-11-23 18:19:57 -05:00
pyproject.toml add disto dep 2025-07-31 20:06:35 -04:00
README.md Init 2024-11-23 18:19:57 -05:00
ruff.toml stop ruff from removing unused imports 2025-07-31 20:07:21 -04:00

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
  • In the event that the function returns any result from BorgRunner, it need's its event attribute changed must be returned to the view.
    • Comments should be used to indicate possible errors from BorgRunner.
  • Error handling for BorgRunner should be done here, not in BorgRunner.

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.html links insert modules' index.html into #content-1
  • index.htmls include header.html and define #content-2
  • #content-2 is 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 %}