Skip to main content

Service lifecycle framework with FastAPI background services, dependency management, and optional desktop GUI launcher

Project description

Web App

Service lifecycle framework with FastAPI background services, dependency management, and optional desktop GUI launcher.

Overview

vcti-webapp provides a Service base class for managing background services with ordered dependencies and thread-safe lifecycle control. FastAPIService extends this to run FastAPI applications via uvicorn in background threads with automatic port discovery. For desktop applications, the optional GUI module adds AppLauncher (pywebview window), StaticDirApp (static file serving), and ZippedApp (serve from ZIP archives).

Installation

Core (services only):

pip install vcti-webapp>=1.0.0

With desktop GUI support:

pip install vcti-webapp[gui]>=1.0.0

With ZIP archive support (includes GUI + vcti-session):

pip install vcti-webapp[zip]>=1.0.0

Quick Start

Background FastAPI service

from fastapi import FastAPI
from vcti.webapp import FastAPIService

app = FastAPI()

@app.get("/health")
async def health():
    return {"status": "ok"}

# Start in background thread with auto-discovered port
with FastAPIService(app, name="api") as svc:
    print(f"Running on http://localhost:{svc.port}")
    # ... do work ...
# Server stops automatically on exit

Service dependencies

from vcti.webapp import Service, FastAPIService, service_dependency

class DatabaseService(Service):
    def _start_service(self):
        self.connection = connect_to_db()
    def _stop_service(self):
        self.connection.close()

db = DatabaseService(name="database")
api = FastAPIService(app, name="api")
api.add_dependency(db)

api.start()   # starts db first, then api
api.stop()    # stops api first, then db (reverse order)

Error recovery

from vcti.webapp import CyclicDependencyError

# Circular dependencies are caught at registration time
try:
    svc_a.add_dependency(svc_b)
except CyclicDependencyError:
    print("Would create a cycle — dependency not added")

# Start failures roll back dependencies automatically
try:
    svc.start()
except RuntimeError:
    # All already-started dependencies have been stopped
    print("Service failed to start, deps cleaned up")

Desktop GUI (requires pywebview)

from vcti.webapp.app_launcher import AppLauncher

launcher = AppLauncher(app, window_title="My App", window_size=(1280, 720))
launcher.start()  # opens desktop window, blocks until closed

Core API

Service (base)

Method Description
start() Start service and dependencies (thread-safe, safe to call from multiple threads)
stop() Stop service and optionally dependencies
add_dependency(service) Register a dependency (returns self, raises CyclicDependencyError on cycle)
is_running() Check if running

FastAPIService

Parameter Default Description
app (required) The FastAPI application
host "127.0.0.1" Bind address (loopback only by default for security)
port None TCP port (None = auto-discover a free port)
ready_timeout 10.0 Seconds to wait for server readiness; 0 to skip
ready_poll_interval 0.05 Seconds between readiness polls
uvicorn_config None Extra kwargs forwarded to uvicorn.Config

GUI classes (optional — vcti-webapp[gui])

Class Purpose
AppLauncher Desktop window via pywebview
StaticDirApp Serve static files from a directory
ZippedApp Extract and serve from ZIP archive

Advanced Usage

Custom uvicorn configuration

# Suppress noisy startup logs
svc = FastAPIService(app, uvicorn_config={"log_level": "warning", "access_log": False})

# TLS termination at uvicorn
svc = FastAPIService(app, uvicorn_config={
    "ssl_keyfile": "key.pem",
    "ssl_certfile": "cert.pem",
})

Slow CI environments

# Increase readiness timeout on slow machines
svc = FastAPIService(app, ready_timeout=30.0, ready_poll_interval=0.1)

Shared dependencies

When multiple services share a dependency, use stop_dependencies=False to prevent the first service to stop from tearing down the shared resource:

db = DatabaseService(name="db")

api = FastAPIService(app, name="api", stop_dependencies=False)
api.add_dependency(db)

worker = WorkerService(name="worker", stop_dependencies=False)
worker.add_dependency(db)

# api.stop() leaves db running — worker still needs it

Static file serving without GUI

StaticDirApp inherits from AppLauncher (which requires pywebview), but you can serve static files without a GUI using plain FastAPIService:

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from vcti.webapp import FastAPIService

app = FastAPI()
app.mount("/static", StaticFiles(directory="./dist"), name="static")

with FastAPIService(app, name="docs-server") as svc:
    print(f"Serving at http://localhost:{svc.port}/static/index.html")

Root redirect (show_index_on_root)

StaticDirApp and ZippedApp redirect GET / to {static_route}/{default_page} by default. Set show_index_on_root=False if you define your own root route or want / to return 404:

StaticDirApp(Path("./dist"), show_index_on_root=False)

Threading

start() and stop() are thread-safe. Calling start() from multiple threads simultaneously is safe — only one thread runs startup; others return immediately. See docs/design.md for details on lock ordering and concurrency guarantees.


Dependencies

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vcti_webapp-1.0.0.tar.gz (18.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vcti_webapp-1.0.0-py3-none-any.whl (13.4 kB view details)

Uploaded Python 3

File details

Details for the file vcti_webapp-1.0.0.tar.gz.

File metadata

  • Download URL: vcti_webapp-1.0.0.tar.gz
  • Upload date:
  • Size: 18.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for vcti_webapp-1.0.0.tar.gz
Algorithm Hash digest
SHA256 af1f6a1aa85870da1746e186ab7ec1304fb7a5a58e3a68588af84f0437d76260
MD5 04213a4f319e7b7297381f7acda330d5
BLAKE2b-256 16a03356626e70e377e8c1a6612728252900b37f6fbe45a27d48836eca04d566

See more details on using hashes here.

Provenance

The following attestation bundles were made for vcti_webapp-1.0.0.tar.gz:

Publisher: publish.yml on vcollab/vcti-python-webapp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vcti_webapp-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: vcti_webapp-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 13.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for vcti_webapp-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5c3ee45fc9908f2f8396a71acf57b1a6ac748698b5f840979a67b8e8866fd26a
MD5 33b61811192868e4bbd518348dff397a
BLAKE2b-256 c0f2e86255f83aba85a98763709f91c35ed071616e4b74ab4c1112f132c16223

See more details on using hashes here.

Provenance

The following attestation bundles were made for vcti_webapp-1.0.0-py3-none-any.whl:

Publisher: publish.yml on vcollab/vcti-python-webapp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page