style: apply black and isort formatting across entire codebase

- Standardize quote style (single to double quotes)
- Reorder and group imports alphabetically
- Fix line breaks and indentation for consistency
- Apply PEP 8 formatting standards

Also updated Makefile to exclude both venv and .venv from code quality checks.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-28 19:30:17 +01:00
parent 13f0094743
commit 21c13ca39b
236 changed files with 8450 additions and 6545 deletions

View File

@@ -8,32 +8,24 @@ Handles theme CRUD operations, preset application, and validation.
import logging
import re
from typing import Optional, Dict, List
from typing import Dict, List, Optional
from sqlalchemy.orm import Session
from app.core.theme_presets import (THEME_PRESETS, apply_preset,
get_available_presets, get_preset_preview)
from app.exceptions.vendor import VendorNotFoundException
from app.exceptions.vendor_theme import (InvalidColorFormatException,
InvalidFontFamilyException,
InvalidThemeDataException,
ThemeOperationException,
ThemePresetAlreadyAppliedException,
ThemePresetNotFoundException,
ThemeValidationException,
VendorThemeNotFoundException)
from models.database.vendor import Vendor
from models.database.vendor_theme import VendorTheme
from models.schema.vendor_theme import (
VendorThemeUpdate,
ThemePresetPreview
)
from app.exceptions.vendor import VendorNotFoundException
from app.exceptions.vendor_theme import (
VendorThemeNotFoundException,
InvalidThemeDataException,
ThemePresetNotFoundException,
ThemeValidationException,
InvalidColorFormatException,
InvalidFontFamilyException,
ThemePresetAlreadyAppliedException,
ThemeOperationException
)
from app.core.theme_presets import (
apply_preset,
get_available_presets,
get_preset_preview,
THEME_PRESETS
)
from models.schema.vendor_theme import ThemePresetPreview, VendorThemeUpdate
logger = logging.getLogger(__name__)
@@ -71,9 +63,9 @@ class VendorThemeService:
Raises:
VendorNotFoundException: If vendor not found
"""
vendor = db.query(Vendor).filter(
Vendor.vendor_code == vendor_code.upper()
).first()
vendor = (
db.query(Vendor).filter(Vendor.vendor_code == vendor_code.upper()).first()
)
if not vendor:
self.logger.warning(f"Vendor not found: {vendor_code}")
@@ -105,12 +97,12 @@ class VendorThemeService:
vendor = self._get_vendor_by_code(db, vendor_code)
# Get theme
theme = db.query(VendorTheme).filter(
VendorTheme.vendor_id == vendor.id
).first()
theme = db.query(VendorTheme).filter(VendorTheme.vendor_id == vendor.id).first()
if not theme:
self.logger.info(f"No custom theme for vendor {vendor_code}, returning default")
self.logger.info(
f"No custom theme for vendor {vendor_code}, returning default"
)
return self._get_default_theme()
return theme.to_dict()
@@ -130,23 +122,16 @@ class VendorThemeService:
"accent": "#ec4899",
"background": "#ffffff",
"text": "#1f2937",
"border": "#e5e7eb"
},
"fonts": {
"heading": "Inter, sans-serif",
"body": "Inter, sans-serif"
"border": "#e5e7eb",
},
"fonts": {"heading": "Inter, sans-serif", "body": "Inter, sans-serif"},
"branding": {
"logo": None,
"logo_dark": None,
"favicon": None,
"banner": None
},
"layout": {
"style": "grid",
"header": "fixed",
"product_card": "modern"
"banner": None,
},
"layout": {"style": "grid", "header": "fixed", "product_card": "modern"},
"social_links": {},
"custom_css": None,
"css_variables": {
@@ -158,7 +143,7 @@ class VendorThemeService:
"--color-border": "#e5e7eb",
"--font-heading": "Inter, sans-serif",
"--font-body": "Inter, sans-serif",
}
},
}
# ============================================================================
@@ -166,10 +151,7 @@ class VendorThemeService:
# ============================================================================
def update_theme(
self,
db: Session,
vendor_code: str,
theme_data: VendorThemeUpdate
self, db: Session, vendor_code: str, theme_data: VendorThemeUpdate
) -> VendorTheme:
"""
Update or create theme for vendor.
@@ -194,9 +176,9 @@ class VendorThemeService:
vendor = self._get_vendor_by_code(db, vendor_code)
# Get or create theme
theme = db.query(VendorTheme).filter(
VendorTheme.vendor_id == vendor.id
).first()
theme = (
db.query(VendorTheme).filter(VendorTheme.vendor_id == vendor.id).first()
)
if not theme:
self.logger.info(f"Creating new theme for vendor {vendor_code}")
@@ -224,15 +206,11 @@ class VendorThemeService:
db.rollback()
self.logger.error(f"Failed to update theme for vendor {vendor_code}: {e}")
raise ThemeOperationException(
operation="update",
vendor_code=vendor_code,
reason=str(e)
operation="update", vendor_code=vendor_code, reason=str(e)
)
def _apply_theme_updates(
self,
theme: VendorTheme,
theme_data: VendorThemeUpdate
self, theme: VendorTheme, theme_data: VendorThemeUpdate
) -> None:
"""
Apply theme updates to theme object.
@@ -251,30 +229,30 @@ class VendorThemeService:
# Update fonts
if theme_data.fonts:
if theme_data.fonts.get('heading'):
theme.font_family_heading = theme_data.fonts['heading']
if theme_data.fonts.get('body'):
theme.font_family_body = theme_data.fonts['body']
if theme_data.fonts.get("heading"):
theme.font_family_heading = theme_data.fonts["heading"]
if theme_data.fonts.get("body"):
theme.font_family_body = theme_data.fonts["body"]
# Update branding
if theme_data.branding:
if theme_data.branding.get('logo') is not None:
theme.logo_url = theme_data.branding['logo']
if theme_data.branding.get('logo_dark') is not None:
theme.logo_dark_url = theme_data.branding['logo_dark']
if theme_data.branding.get('favicon') is not None:
theme.favicon_url = theme_data.branding['favicon']
if theme_data.branding.get('banner') is not None:
theme.banner_url = theme_data.branding['banner']
if theme_data.branding.get("logo") is not None:
theme.logo_url = theme_data.branding["logo"]
if theme_data.branding.get("logo_dark") is not None:
theme.logo_dark_url = theme_data.branding["logo_dark"]
if theme_data.branding.get("favicon") is not None:
theme.favicon_url = theme_data.branding["favicon"]
if theme_data.branding.get("banner") is not None:
theme.banner_url = theme_data.branding["banner"]
# Update layout
if theme_data.layout:
if theme_data.layout.get('style'):
theme.layout_style = theme_data.layout['style']
if theme_data.layout.get('header'):
theme.header_style = theme_data.layout['header']
if theme_data.layout.get('product_card'):
theme.product_card_style = theme_data.layout['product_card']
if theme_data.layout.get("style"):
theme.layout_style = theme_data.layout["style"]
if theme_data.layout.get("header"):
theme.header_style = theme_data.layout["header"]
if theme_data.layout.get("product_card"):
theme.product_card_style = theme_data.layout["product_card"]
# Update custom CSS
if theme_data.custom_css is not None:
@@ -289,10 +267,7 @@ class VendorThemeService:
# ============================================================================
def apply_theme_preset(
self,
db: Session,
vendor_code: str,
preset_name: str
self, db: Session, vendor_code: str, preset_name: str
) -> VendorTheme:
"""
Apply a theme preset to vendor.
@@ -322,9 +297,9 @@ class VendorThemeService:
vendor = self._get_vendor_by_code(db, vendor_code)
# Get or create theme
theme = db.query(VendorTheme).filter(
VendorTheme.vendor_id == vendor.id
).first()
theme = (
db.query(VendorTheme).filter(VendorTheme.vendor_id == vendor.id).first()
)
if not theme:
self.logger.info(f"Creating new theme for vendor {vendor_code}")
@@ -338,7 +313,9 @@ class VendorThemeService:
db.commit()
db.refresh(theme)
self.logger.info(f"Preset '{preset_name}' applied successfully to vendor {vendor_code}")
self.logger.info(
f"Preset '{preset_name}' applied successfully to vendor {vendor_code}"
)
return theme
except (VendorNotFoundException, ThemePresetNotFoundException):
@@ -349,9 +326,7 @@ class VendorThemeService:
db.rollback()
self.logger.error(f"Failed to apply preset to vendor {vendor_code}: {e}")
raise ThemeOperationException(
operation="apply_preset",
vendor_code=vendor_code,
reason=str(e)
operation="apply_preset", vendor_code=vendor_code, reason=str(e)
)
def get_available_presets(self) -> List[ThemePresetPreview]:
@@ -399,9 +374,9 @@ class VendorThemeService:
vendor = self._get_vendor_by_code(db, vendor_code)
# Get theme
theme = db.query(VendorTheme).filter(
VendorTheme.vendor_id == vendor.id
).first()
theme = (
db.query(VendorTheme).filter(VendorTheme.vendor_id == vendor.id).first()
)
if not theme:
raise VendorThemeNotFoundException(vendor_code)
@@ -423,9 +398,7 @@ class VendorThemeService:
db.rollback()
self.logger.error(f"Failed to delete theme for vendor {vendor_code}: {e}")
raise ThemeOperationException(
operation="delete",
vendor_code=vendor_code,
reason=str(e)
operation="delete", vendor_code=vendor_code, reason=str(e)
)
# ============================================================================
@@ -459,9 +432,9 @@ class VendorThemeService:
# Validate layout values
if theme_data.layout:
valid_layouts = {
'style': ['grid', 'list', 'masonry'],
'header': ['fixed', 'static', 'transparent'],
'product_card': ['modern', 'classic', 'minimal']
"style": ["grid", "list", "masonry"],
"header": ["fixed", "static", "transparent"],
"product_card": ["modern", "classic", "minimal"],
}
for layout_key, layout_value in theme_data.layout.items():
@@ -472,7 +445,7 @@ class VendorThemeService:
field=layout_key,
validation_errors={
layout_key: f"Must be one of: {', '.join(valid_layouts[layout_key])}"
}
},
)
def _is_valid_color(self, color: str) -> bool:
@@ -489,7 +462,7 @@ class VendorThemeService:
return False
# Check for hex color format (#RGB or #RRGGBB)
hex_pattern = r'^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$'
hex_pattern = r"^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$"
return bool(re.match(hex_pattern, color))
def _is_valid_font(self, font: str) -> bool: