Skip to content

Releases: offerrall/FuncToWeb

1.6.0 Now functoweb is much more powerful

06 Jun 12:49

Choose a tag to compare

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 escape uploads_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

  • Params subclasses 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; /doc is the honest
    machine-readable description (re-enable via fastapi_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 the aiofiles dependency.

Fixed

  • Internal URLs work under any mount prefix or reverse-proxy root_path.
  • workers/reload passed to run() now raise a clear error instead of being
    silently ignored (use create_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 Params setups (duplicate field names, nested or optional Params)
    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

01 May 19:30

Choose a tag to compare

[1.0.1] - 2026-05-01

Added

  • Custom frontend hosting via front_dir and assets_dirrun() now accepts two new parameters to serve a custom frontend from the same process

    • front_dir: directory mounted at /front with html=True for SPA-style routing — drop a static site, landing page, or built React/Vue/Svelte bundle next to your Python functions
    • assets_dir: directory mounted at /assets for 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
  • /doc endpoint — auto-generated, machine-readable API documentation

    • Every app now exposes GET /doc returning a single plain-text document
    • Lists all registered functions (visible and hidden) with their parameters,
      constraints, choices, defaults, and a working curl example for each
    • Parameters are emitted as JSON, making the doc directly parseable
    • File parameters include an upload_info block 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
  • Embed mode for iframe integration — append ?__embed=1 to 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

15 Apr 00:57

Choose a tag to compare

[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 pytypeinput metadata. 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

13 Jan 10:22

Choose a tag to compare

[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

11 Jan 13:05

Choose a tag to compare

[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 of Literal[get_options]
    • Provides better IDE support and clearer intent
    • Example:
    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, and bool types
  • Fully backwards compatible - Literal[func] syntax still supported

0.9.11

07 Jan 21:48

Choose a tag to compare

[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

v0.9.10

01 Jan 20:03

Choose a tag to compare

[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 files
    • FileResponse(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

23 Dec 08:14

Choose a tag to compare

[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 FileResponse processing 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

20 Dec 05:51

Choose a tag to compare

[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

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

0.9.7

10 Dec 21:15

Choose a tag to compare

[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 needed
    • cleanup_hours - now hardcoded to 1 hour
  • Workers Limitation

    • workers > 1 no 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=False if needed
  • Directory Configuration

    • New parameter: uploads_dir (default: "./uploads")
    • New parameter: returns_dir (default: "./returned_files")

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.py module
    • Simplified file_handler.py
    • Faster startup (no database initialization)

Fixed

  • Database lock errors eliminated
  • Race conditions eliminated
  • Improved startup performance

Documentation

  • Updated all docs to remove SQLite references
  • Removed db_location and cleanup_hours from examples
  • Added auto_delete_uploads documentation
  • 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_location removed (use returns_dir)
  • cleanup_hours removed (hardcoded to 1 hour)
  • func_to_web.db no longer created

Non-Breaking:

  • workers parameter 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.