Skip to main content

abstract_flask

The staged bundle provides ops.sh ACTION [--plan] and scripts/*.sh for local Python installs and PyPI/GitHub push paths. Its Python source and pyproject.toml are at this directory's root.

A composable toolkit for standing up Flask APIs without repeating yourself. Handles blueprint discovery, CORS, request parsing, endpoint introspection, and route generation — so the only code you write is the code that matters.

Install

pip install abstract_flask

Quickstart

# my_api/__init__.py
from . import routes
from abstract_flask import get_Flask_app

app = get_Flask_app(routes=routes, allowed_origins=["https://yourdomain.com"])

That's it. Blueprints are discovered from any *_bp objects in your routes module, CORS is applied, and introspection endpoints are registered automatically.

Full signature

app = get_Flask_app(
    name="my_api",              # Flask app name (default: caller's __name__)
    routes=routes,              # module to scan for *_bp Blueprints
    bp_list=None,               # or pass blueprints explicitly
    url_prefix="v1",            # prefix for blueprint registration + filtered /endpoints
    allowed_origins=["https://example.com"],
    supports_credentials=True,
)

Running

from abstract_flask import main_flask_start

main_flask_start(app, key_head="MYAPI", env_path=".env")
# reads MYAPI_DEBUG, MYAPI_HOST, MYAPI_PORT from env

Package structure

abstract_flask/
├── abstract_flask.py        # App factory, CORS, audit logging, introspection
├── request_utils/
│   ├── request_utils.py     # get_request_data, extract_request_data
│   ├── get_requests.py      # required_keys, execute_request, get_spec_kwargs
│   └── parse_utils.py       # parse_request, parse_and_spec_vars
├── network_utils/
│   └── ip_utils.py          # get_host_ip, get_user_ip, get_ip_addr
├── user_utils/
│   └── user_utils.py        # get_user_name (from request or fallback)
└── generator/
    ├── generateFlaskRoute.py # Auto-generate Flask routes from Python files
    └── help_utils.py         # ?help introspection for any endpoint

Core modules

App factory (abstract_flask.py)

Function Purpose
get_Flask_app(...) One-call app factory: blueprints, CORS, logging, introspection
get_bp(name, abs_path) Create a named Blueprint with a logger
main_flask_start(app) Run the app using env-driven host/port/debug

Every app gets these endpoints for free:

  • GET /endpoints — all registered routes
  • GET /<prefix>/endpoints — routes under that prefix
  • GET /prefixes — unique top-level route segments

Request utilities (request_utils/)

from abstract_flask.request_utils import get_request_data, required_keys, parse_request
  • get_request_data(req) — Returns a dict from JSON body, form data, or query string (checked in that order).
  • extract_request_data(req, res_type) — Full extraction: user, IP, headers, cookies, files, metadata. Pass res_type to narrow scope.
  • required_keys(keys, req, defaults) — Validate that required keys are present; returns the data dict or a 400 error payload.
  • parse_request(req) — Split a request into positional args and kwargs.
  • get_spec_kwargs(var_types, args, **kwargs) — Type-coerced argument extraction against a schema.

Route generator (generator/)

Auto-generate Flask endpoints from plain Python files:

from abstract_flask.generator import generate_from_files

source = generate_from_files(
    directory="./my_functions",
    bp_name="auto_bp",
    url_prefix="generated",
)

Every public function becomes a GET/POST endpoint. Async functions are preserved. Pass ?help to any generated endpoint to get parameter introspection via offer_help.

Register routes programmatically against an existing blueprint:

from abstract_flask.generator import register_category

register_category(bp, "math", {
    "add": lambda a, b: a + b,
    "multiply": lambda a, b: a * b,
})
# creates /math/add, /math/multiply

Network utilities (network_utils/)

from abstract_flask.network_utils import get_host_ip, get_user_ip

User utilities (user_utils/)

from abstract_flask.user_utils import get_user_name

Resolves username from the request's .user attribute, falling back to IP-based lookup via UserIPManager.

Dependencies

  • flask, flask_cors, werkzeug
  • abstract_utilities, abstract_security, abstract_queries

License

MIT

Author

putkoff — partners@abstractendeavors.com

Declarative Flask route schema

get_Flask_app accepts a nested route dictionary directly. Callable leaves keep its original GET/POST and { "result": ... } response convention. A route spec leaf can describe exact Flask behavior:

from abstract_flask import get_Flask_app

routes = {"fleet": {"worker": {
    "view": worker_detail,
    "rule": "/fleet/workers/<worker_id>",
    "methods": ["GET"],
    "inputs": "path",       # or "merged" for query/form/JSON plus URL variables
    "response": "native", # or "result" for the original response wrapper
}}}
app = get_Flask_app(name="fleet", routes=routes, dual_prefix="/api")

A spec may use rules for several URL aliases and endpoint to name the Flask endpoint. strict_slashes defaults to False; set it to True when migrating an exact existing URL contract. Native responses preserve Flask responses, status tuples, streaming responses, and ordinary dictionaries. URL variables take precedence over submitted fields in merged input mode.

An arm entry point in arms_group may export a route dictionary as well as a Blueprint. The factory creates and mounts its Blueprint automatically.

The tree is the path

Absolute rules are rarely needed: dict nesting is the URL, a <param> key (<run_id>, <int:tid>, <path:key>) is a path parameter, and the "" key is a node's own index route. Path parameters reach plain callables and spec leaves alike as the same-named keyword argument, merged with the query/form/JSON body (the URL value wins). A list of specs on one key puts several method-specific views on one URL. spec() writes the leaf dict explicitly:

from abstract_flask import register_categories, spec, merge_categories, describe_categories

ALL_CATEGORIES = {"llm": {"benchmark": {
    "runs": {
        "": spec(benchmark_runs, "GET", response="native"),          # GET /llm/benchmark/runs
        "<run_id>": spec(benchmark_run_get, "GET", response="native"),  # GET /llm/benchmark/runs/<run_id>
    },
    "run": spec(benchmark_run, "POST", response="native"),           # POST /llm/benchmark/run
    "status": benchmark_status,                                       # GET+POST, {"result": ...}
}}, "help": {"sessions": [                                            # one URL, two methods
    spec(sessions_list, "GET", response="native"),
    spec(sessions_start, "POST", response="native"),
]}}
register_categories(bp, ALL_CATEGORIES)

Handlers are plain functions: keyword arguments in, JSON-able data out ((payload, status) when a non-200 matters under response="native"). They never read flask.request; the registrar does that. Because every section of an app states its surface as such a tree, the sections compose: merge_categories(a.ALL_CATEGORIES, b.ALL_CATEGORIES) is the whole surface as one dict (two sections claiming the same leaf path is an error), and describe_categories(tree) renders it as a JSON catalog (path, methods, kind, inputs, response, view, doc, params) that another service can consume without Flask. Endpoint names drop the angle brackets and converters of path parameters (llm_benchmark_runs_run_id).

Metadata

Release files for abstract-flask 0.0.0.1071

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for abstract-flask 0.0.0.1071
File Size Uploaded Provenance
abstract_flask-0.0.0.1071.tar.gz 41.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for abstract-flask 0.0.0.1071
File Interpreter ABI Platform
abstract_flask-0.0.0.1071-py3-none-any.whl Python 3 none any Details

Total release size: 80.2 kB

Release files / abstract_flask-0.0.0.1071.tar.gz

Download URL abstract_flask-0.0.0.1071.tar.gz
Size 41.5 kB
Tags Source
SHA-256 checksum
How to use checksums
b7dd463e60e2afa189c1003ac79f650491bde8951d68db828d743489f9b1cf2d
BLAKE2b-256 checksum
How to use checksums
7e446ae05d59e5a6410b891e238063f71a901528e3c30108079b8f8c14417e8c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / abstract_flask-0.0.0.1071-py3-none-any.whl

Download URL abstract_flask-0.0.0.1071-py3-none-any.whl
Size 38.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
91e9ca691a7522ad16c23ad9bf155320fabc40b0153bbfadca160e3d0d3cf0ce
BLAKE2b-256 checksum
How to use checksums
480a05d1609cc1cb1cf79c08c35dc6ed04c16816757dfe114cbe39307e51dfd2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Security for abstract-flask 0.0.0.1071

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.0.0.1071 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page