Skip to content

Commit 09a70b6

Browse files
committed
0.9.5
1 parent d49e2c5 commit 09a70b6

7 files changed

Lines changed: 28 additions & 20 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## [0.9.5] - 2025-12-09
4+
5+
### Added
6+
- **New Generic `File` Type**: Added support for a generic `File` type hint.
7+
- Use `from func_to_web.types import File` to accept uploaded files of **any** extension.
8+
- **Expanded File Extensions**: Significantly broadened the list of supported formats for specific file types.
9+
310
## [0.9.4] - 2025-12-08
411

512
### Added

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Func To Web 0.9.4
1+
# Func To Web 0.9.5
22

33
[![PyPI version](https://img.shields.io/pypi/v/func-to-web.svg)](https://pypi.org/project/func-to-web/)
44
[![Python](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
@@ -50,7 +50,7 @@ Complete documentation with **examples and screenshots** for each feature:
5050
### **Input Types**
5151
- **[Basic Types](https://offerrall.github.io/FuncToWeb/types/)**: `int`, `float`, `str`, `bool`, `date`, `time`
5252
- **[Special Types](https://offerrall.github.io/FuncToWeb/types/)**: `Color`, `Email`
53-
- **[File Uploads](https://offerrall.github.io/FuncToWeb/files/)**: `ImageFile`, `DataFile`, `TextFile`, `DocumentFile`
53+
- **[File Uploads](https://offerrall.github.io/FuncToWeb/files/)**: `File`, `ImageFile`, `DataFile`, `TextFile`, `DocumentFile`
5454
- **[Dynamic Lists](https://offerrall.github.io/FuncToWeb/lists/)**: `list[Type]` with add/remove buttons
5555
- **[Optional Fields](https://offerrall.github.io/FuncToWeb/optional/)**: `Type | None` with toggle switches
5656
- **[Dropdowns](https://offerrall.github.io/FuncToWeb/dropdowns/)**: Static (`Literal`, `Enum`) or Dynamic (`Literal[func]`)

docs/files.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ func-to-web provides specialized file types for different use cases:
1010

1111
```python
1212
from func_to_web import run
13-
from func_to_web.types import ImageFile, DataFile, TextFile, DocumentFile
13+
from func_to_web.types import ImageFile, DataFile, TextFile, DocumentFile, File
1414

1515
def process_files(
16-
photo: ImageFile, # .png, .jpg, .jpeg, .gif, .webp
17-
data: DataFile, # .csv, .xlsx, .xls, .json
18-
notes: TextFile, # .txt, .md, .log
19-
report: DocumentFile # .pdf, .doc, .docx
16+
any_file: File, # any file type
17+
photo: ImageFile, # .png, .jpg, .jpeg, .gif, .webp...
18+
data: DataFile, # .csv, .xlsx, .xls, .json...
19+
notes: TextFile, # .txt, .md, .log...
20+
report: DocumentFile # .pdf, .doc, .docx...
2021
):
2122
return "Files uploaded successfully!"
2223

func_to_web/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from .build_form_fields import build_form_fields
2222
from .process_result import process_result
2323

24-
__version__ = "0.9.3"
24+
__version__ = "0.9.5"
2525

2626
CHUNK_SIZE = 8 * 1024 * 1024 # 8MB
2727
FILE_BUFFER_SIZE = 8 * 1024 * 1024 # 8MB

func_to_web/build_form_fields.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from datetime import date, time
22
from typing import Literal, get_args, get_origin, Any
33

4-
from .types import COLOR_PATTERN, EMAIL_PATTERN
4+
from .types import COLOR_PATTERN, EMAIL_PATTERN, ANY_FILE_PATTERN
55

66
PATTERN_TO_HTML_TYPE = {COLOR_PATTERN: 'color', EMAIL_PATTERN: 'email'}
77

@@ -96,16 +96,12 @@ def build_form_fields(params_info: dict) -> list[dict[str, Any]]:
9696
field = {
9797
'name': name,
9898
'default': serialized_default,
99-
# REGLA SIMPLE: Las listas SIEMPRE son required=True
100-
# Si el campo está habilitado (no opcional O toggle ON), debe tener valor
101-
# Las listas nunca pueden estar vacías, si se quiere vacío usar None
10299
'required': True if info.is_list else not info.is_optional,
103100
'is_optional': info.is_optional,
104101
'optional_enabled': info.optional_enabled,
105102
'is_list': info.is_list
106103
}
107104

108-
# Si es una lista, extraer los constraints de lista (min_length, max_length)
109105
if info.is_list and info.list_field_info and hasattr(info.list_field_info, 'metadata'):
110106
for c in info.list_field_info.metadata:
111107
cn = type(c).__name__
@@ -174,8 +170,11 @@ def build_form_fields(params_info: dict) -> list[dict[str, Any]]:
174170
if hasattr(c, 'pattern') and c.pattern:
175171
pattern = c.pattern
176172

173+
# Generic File input (accepts everything)
174+
if pattern == ANY_FILE_PATTERN:
175+
field['type'] = 'file'
177176
# File input detection
178-
if pattern.startswith(r'^.+\.(') and pattern.endswith(r')$'):
177+
elif pattern.startswith(r'^.+\.(') and pattern.endswith(r')$'):
179178
field['type'] = 'file'
180179
exts = pattern[6:-2].split('|')
181180
field['accept'] = '.' + ',.'.join(exts)

func_to_web/types.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
COLOR_PATTERN = r'^#(?:[0-9a-fA-F]{3}){1,2}$'
55
EMAIL_PATTERN = r'^[^@]+@[^@]+\.[^@]+$'
6+
ANY_FILE_PATTERN = r'^.+$'
67

78
def _file_pattern(*extensions):
89
"""Generate regex pattern for file extensions."""
@@ -12,11 +13,11 @@ def _file_pattern(*extensions):
1213

1314
Color = Annotated[str, Field(pattern=COLOR_PATTERN)]
1415
Email = Annotated[str, Field(pattern=EMAIL_PATTERN)]
15-
ImageFile = Annotated[str, Field(pattern=_file_pattern('png', 'jpg', 'jpeg', 'gif', 'webp'))]
16-
DataFile = Annotated[str, Field(pattern=_file_pattern('csv', 'xlsx', 'xls', 'json'))]
17-
TextFile = Annotated[str, Field(pattern=_file_pattern('txt', 'md', 'log'))]
18-
DocumentFile = Annotated[str, Field(pattern=_file_pattern('pdf', 'doc', 'docx'))]
19-
16+
ImageFile = Annotated[str, Field(pattern=_file_pattern('png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'tiff', 'svg', 'ico', 'heic', 'avif'))]
17+
DataFile = Annotated[str, Field(pattern=_file_pattern('csv', 'xlsx', 'xls', 'json', 'xml', 'yaml', 'yml'))]
18+
TextFile = Annotated[str, Field(pattern=_file_pattern('txt', 'md', 'log', 'rtf'))]
19+
DocumentFile = Annotated[str, Field(pattern=_file_pattern('pdf', 'doc', 'docx', 'odt', 'ppt', 'pptx', 'odp', 'xls', 'xlsx', 'ods'))]
20+
File = Annotated[str, Field(pattern=ANY_FILE_PATTERN)]
2021

2122
class _OptionalEnabledMarker:
2223
"""Internal marker for OptionalEnabled"""

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "func-to-web"
7-
version = "0.9.4"
7+
version = "0.9.5"
88
authors = [
99
{name = "Beltrán Offerrall"}
1010
]

0 commit comments

Comments
 (0)