- Create backend/services/image_storage.py with 4 core functions:
- sanitize_filename(): remove unsafe chars, limit to 255 chars, convert to lowercase
- get_unique_filename(): handle collisions with UUID suffix (format: {name}_{uuid8}_{variant}.jpg)
- ensure_image_directories(): create /images/ root and category subdirs on startup
- save_image(): save bytes to /images/{category}/{filename}, returns relative path
- Create comprehensive test suite (22 tests) covering all functionality
- Integrate ensure_image_directories() into FastAPI startup event
- Directory structure: /images/{category}/{filename}
- Collision handling: auto-suffix with UUID if filename exists
- All tests passing, pathlib.Path for safe operations
39 lines
1.0 KiB
Python
39 lines
1.0 KiB
Python
__all__ = 'compiled', 'VERSION', 'version_info'
|
|
|
|
VERSION = '1.10.26'
|
|
|
|
try:
|
|
import cython # type: ignore
|
|
except ImportError:
|
|
compiled: bool = False
|
|
else: # pragma: no cover
|
|
try:
|
|
compiled = cython.compiled
|
|
except AttributeError:
|
|
compiled = False
|
|
|
|
|
|
def version_info() -> str:
|
|
import platform
|
|
import sys
|
|
from importlib import import_module
|
|
from pathlib import Path
|
|
|
|
optional_deps = []
|
|
for p in ('devtools', 'dotenv', 'email-validator', 'typing-extensions'):
|
|
try:
|
|
import_module(p.replace('-', '_'))
|
|
except ImportError:
|
|
continue
|
|
optional_deps.append(p)
|
|
|
|
info = {
|
|
'pydantic version': VERSION,
|
|
'pydantic compiled': compiled,
|
|
'install path': Path(__file__).resolve().parent,
|
|
'python version': sys.version,
|
|
'platform': platform.platform(),
|
|
'optional deps. installed': optional_deps,
|
|
}
|
|
return '\n'.join('{:>30} {}'.format(k + ':', str(v).replace('\n', ' ')) for k, v in info.items())
|