feat(phase1): add image storage utilities

- 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
This commit is contained in:
2026-04-20 21:57:26 +03:00
parent 39fab336ba
commit ea49cd6e4a
4487 changed files with 1305959 additions and 4 deletions

View File

@@ -0,0 +1,27 @@
from typing import final
class PluggyWarning(UserWarning):
"""Base class for all warnings emitted by pluggy."""
__module__ = "pluggy"
@final
class PluggyTeardownRaisedWarning(PluggyWarning):
"""A plugin raised an exception during an :ref:`old-style hookwrapper
<old_style_hookwrappers>` teardown.
Such exceptions are not handled by pluggy, and may cause subsequent
teardowns to be executed at unexpected times, or be skipped entirely.
This is an issue in the plugin implementation.
If the exception is unintended, fix the underlying cause.
If the exception is intended, switch to :ref:`new-style hook wrappers
<hookwrappers>`, or use :func:`result.force_exception()
<pluggy.Result.force_exception>` to set the exception instead of raising.
"""
__module__ = "pluggy"