Releases: offerrall/FuncToWeb
1.6.0 Now functoweb is much more powerful
v1.6.0
Versions 1.0.2 and 1.5.0 were never shipped to PyPI, so these notes describe
where FuncToWeb stands today rather than a diff against an older published
build.
FuncToWeb turns a typed Python function into a web UI, an HTTP endpoint and an
embeddable form, all at once. Three ways to use it: standalone (run), mounted
inside an existing FastAPI app (create_app), or embedded into any site via
<iframe> with URL prefill. Inputs and outputs are derived from your type
hints; auto-generated API docs live at /doc.
Still pre-2.0.0 and fast-moving — pin your version (func-to-web==1.6.0) and
read the CHANGELOG before upgrading.
Security
- Fixed a path traversal vulnerability in file uploads. The original filename
from the multipart request was joined into the save path without
sanitization, allowing../sequences to escapeuploads_dir. Filenames are
now reduced to their final path component.
Summary of changes since the last published release
Added
create_app()— build the app without starting a server: mount it inside a
larger FastAPI app, or serve by import string to unlock--workers/
--reload. All internal URLs adapt to any prefix automatically.
Changed
Paramssubclasses are now frozen dataclasses: constructible anywhere,
comparable, hashable, immutable; cross-field validation via__post_init__.- Static CSS/JS bundles are built in memory and served from routes (no temp-dir
files), browser-cacheable with ETag. - Returned-file cleanup is opportunistic (on save/download, throttled) instead
of a per-process background timer. - Default uploads/returns directories moved to the OS temp folder.
- Swagger UI / ReDoc / OpenAPI schema are off by default;
/docis the honest
machine-readable description (re-enable viafastapi_config). - Multi-function pages show a "back to index" button instead of a sidebar.
Removed
- Built-in auth (use a reverse proxy),
front_dir/assets_dir(compose with
StaticFiles),keep_uploads,ActionTable,HiddenFunction, function
groups, and theaiofilesdependency.
Fixed
- Internal URLs work under any mount prefix or reverse-proxy
root_path. workers/reloadpassed torun()now raise a clear error instead of being
silently ignored (usecreate_app()+ import string).- The package no longer ships unrelated top-level folders into site-packages.
- Returned files are stream-copied instead of loaded fully into RAM.
- Result serialization no longer blocks the event loop.
- Concurrent requests no longer race on a shared mutable param list.
- Invalid
Paramssetups (duplicate field names, nested or optionalParams)
are rejected at startup with a clear error. - Server-side validation errors (422/400) are now shown in the UI instead of
being silently dropped.
See the CHANGELOG for full details and migration notes.
Full docs: see the docs/ folder · Made by Beltrán Offerrall
v1.0.1
[1.0.1] - 2026-05-01
Added
-
Custom frontend hosting via
front_dirandassets_dir—run()now accepts two new parameters to serve a custom frontend from the same processfront_dir: directory mounted at/frontwithhtml=Truefor SPA-style routing — drop a static site, landing page, or built React/Vue/Svelte bundle next to your Python functionsassets_dir: directory mounted at/assetsfor images, fonts, downloads or any static files referenced by your frontend or forms- Both are excluded from the auth middleware so static content is reachable without login
- Lets a single FuncToWeb process host the form UI, the API and a full custom frontend — no separate web server needed
-
/docendpoint — auto-generated, machine-readable API documentation- Every app now exposes
GET /docreturning a single plain-text document - Lists all registered functions (visible and hidden) with their parameters,
constraints, choices, defaults, and a workingcurlexample for each - Parameters are emitted as JSON, making the doc directly parseable
- File parameters include an
upload_infoblock describing the multipart
transport, field name, and whether multiple files are accepted - Dynamic dropdowns (
Dropdown(func)) are flagged with"dynamic": true
so consumers know the listed options are a snapshot, not an exhaustive set - URLs in examples use a
<base_url>placeholder, making the doc portable
across local, proxied and production deployments - Designed to be consumed by humans, scripts, or AI agents calling the API
without prior knowledge of the app
- Every app now exposes
-
Embed mode for iframe integration — append
?__embed=1to any function URL- Strips the sidebar, theme toggle, and outer chrome at runtime
- Forces a transparent background so the form blends into the parent page
- Removes the container's max-width, padding, shadow and border
- Lets you drop a FuncToWeb form into an existing web app via
<iframe>with
no visual seams — combine with URL prefill (?param=value) for a fully
pre-configured embedded form
v1.0.0
[1.0.0] - 2026-04-15
Biggest release so far. The library has been rewritten from the ground up — most existing code works without changes or with very minor ones.
The biggest structural change is that FuncToWeb is now split into three independent libraries:
- pytypeinput — Analyzes Python type hints and extracts UI metadata. No web dependency.
- pytypeinputweb — Renders HTML forms from
pytypeinputmetadata. Use it in your own server. - func-to-web — The full stack.
This opens up a lot of new possibilities — for example, using FuncToWeb as a support layer inside an existing web app, exposing individual utility functions without building a full tool. There are other interesting approaches worth exploring that the docs cover.
A full re-read of the documentation is recommended.
This is a stable beta. I'll be actively fixing issues and improving things over the coming days.
0.9.13
[0.9.13] - 2025-01-13
Added
- Multiple file upload improvements for
list[FileType]- New "+" button next to file input allows adding files from different folders
- Visual file list shows selected files with names, sizes, and remove buttons
- Supports all file types:
ImageFile,VideoFile,AudioFile,DataFile,TextFile,DocumentFile,File - Files can be selected from one folder, then more added from other folders
- Individual files can be removed before upload
- File list automatically hides when optional field is disabled
0.9.12
[0.9.12] - 2025-01-11
Added
- New
Dropdown()type for dynamic dropdowns - cleaner, type-safe syntax for dropdowns with runtime-generated options- Use
Annotated[str, Dropdown(get_options)]instead ofLiteral[get_options] - Provides better IDE support and clearer intent
- Example:
- Use
from typing import Annotated
from func_to_web.types import Dropdown
def get_users():
return ['alice', 'bob', 'charlie']
def send_message(to: Annotated[str, Dropdown(get_users)]):
return f"Message sent to {to}"- Works with
str,int,float, andbooltypes - Fully backwards compatible -
Literal[func]syntax still supported
0.9.11
[0.9.11] - 2026-01-07
Added
- Grouped functions feature: organize multiple functions into collapsible accordion groups
- Pass a dictionary to
run()with group names as keys and function lists as values - Example:
run({'Math': [add, multiply], 'Text': [upper, lower]}) - Groups display as accordion cards with badges showing function count
- Only one group can be open at a time for clean navigation
- Fully backwards compatible with existing single function and list modes
- Pass a dictionary to
v0.9.10
[0.9.10] - 2026-01-01
Added
- VideoFile and AudioFile types for file uploads
VideoFile: Accepts common video formats (mp4, mov, avi, mkv, wmv, flv, webm, mpeg, mpg)AudioFile: Accepts common audio formats (mp3, wav, aac, flac, ogg, m4a)
- Updated ImageFile type to include additional formats (raw, psd)
- FileResponse now accepts either binary data or file path
FileResponse(data=bytes, filename="file.ext")- for in-memory filesFileResponse(path="/path/to/file", filename="file.ext")- for existing files on disk- Files specified by path are copied to returns_dir for consistent management
- Both approaches result in automatic 1-hour cleanup
Changed
- Changed default title of index page from "Function Tools" to "Menu"
v0.9.9
[0.9.9] - 2025-12-23
Performance
- Non-blocking Execution: Standard Python functions (
def) are now automatically executed in a thread pool. This prevents CPU-heavy tasks from blocking the main event loop. - Async Disk I/O: Offloaded
FileResponseprocessing and disk writing to background threads.- Generating and saving large files (GB+) no longer freezes the server.
- The UI remains responsive for other users while files are being written to disk.
- Improved Concurrency: The server can now handle multiple simultaneous heavy requests (calculations or downloads) without queue blocking.
v0.9.8
[0.9.8] - 2025-12-21
Changed
- FileResponse Filename Limit: 150-character maximum (Pydantic validated)
Security
- Filename Sanitization: User-uploaded files sanitized against directory traversal, reserved names, and special characters
- Format:
{sanitized_name}_{32char_uuid}.{ext} - 100-char limit on user portion, ~143 total length
- Preserves original name for identification
- Format:
Fixed
- File Lists: Fixed bug where
list[File]would fail with JSON parsing error- Backend now uses
form_data.getlist()to properly group uploaded files validate_list_param()accepts pre-processed lists in addition to JSON strings
- Backend now uses
0.9.7
[0.9.7] - 2025-12-10
Philosophy Change
Version 0.9.6 introduced SQLite for file tracking, blocked multiple workers, and added complex configuration. This was overengineered. func-to-web should be simple, fast, and reliable.
0.9.7 returns to simplicity with filesystem-based tracking, multiple workers support, and sensible defaults.
Removed
-
SQLite Database
- No more database files or locks
- File metadata encoded directly in filenames
- Format:
{uuid}___{timestamp}___{filename}
-
Parameters Removed
db_location- no longer neededcleanup_hours- now hardcoded to 1 hour
-
Workers Limitation
workers > 1no longer blocked- Scale vertically without restrictions
Added
-
Automatic Upload Cleanup
- New parameter:
auto_delete_uploads(default:True) - Uploaded files deleted after function completes
- Disable with
auto_delete_uploads=Falseif needed
- New parameter:
-
Directory Configuration
- New parameter:
uploads_dir(default:"./uploads") - New parameter:
returns_dir(default:"./returned_files")
- New parameter:
Changed
-
File Retention
- Returned files deleted 1 hour after creation (hardcoded)
- No download tracking needed
- Cleanup runs every hour automatically
-
Multiple Workers
- Now supported like any other Uvicorn option
- Each worker runs independent cleanup
- File operations are atomic, no conflicts
-
Architecture
- Removed
db_manager.pymodule - Simplified
file_handler.py - Faster startup (no database initialization)
- Removed
Fixed
- Database lock errors eliminated
- Race conditions eliminated
- Improved startup performance
Documentation
- Updated all docs to remove SQLite references
- Removed
db_locationandcleanup_hoursfrom examples - Added
auto_delete_uploadsdocumentation - Updated API reference (removed
db_manager)
Migration from 0.9.6
Before:
run(my_function, db_location="/data", cleanup_hours=48)After:
run(my_function, uploads_dir="/data/uploads", returns_dir="/data/returns")
# Files now expire after 1 hour (hardcoded)Breaking Changes:
db_locationremoved (usereturns_dir)cleanup_hoursremoved (hardcoded to 1 hour)func_to_web.dbno longer created
Non-Breaking:
workersparameter now supported- All other parameters unchanged
Summary
0.9.6 was overengineered. 0.9.7 is simple again: no database, automatic cleanup, multiple workers supported. Filesystem operations are fast, atomic, and sufficient.