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:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user