Spaces:
Sleeping
Sleeping
File size: 4,095 Bytes
21d27b2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
"""
Utility functions for the Logo Downloader application
"""
import os
import re
import json
import time
from pathlib import Path
from typing import List, Optional
from urllib.parse import urlparse
import logging
from services.appconfig import IMAGE_SIGNATURES, MIN_FILE_SIZE, MAX_FILE_SIZE
# Setup logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def create_safe_filename(name: str) -> str:
"""
Create a safe filename from entity name
Args:
name (str): Entity name
Returns:
str: Safe filename
"""
safe_name = re.sub(r'[^\w\s-]', '', name).strip()
safe_name = re.sub(r'[-\s]+', '_', safe_name)
return safe_name
def get_file_extension(url: str) -> str:
"""
Extract file extension from URL
Args:
url (str): Image URL
Returns:
str: File extension
"""
parsed_url = urlparse(url)
extension = os.path.splitext(parsed_url.path)[1]
if not extension or extension.lower() not in ['.png', '.jpg', '.jpeg', '.svg', '.webp']:
extension = '.png'
return extension
def is_valid_image_file(filepath: str) -> bool:
"""
Validate if file is a proper image
Args:
filepath (str): Path to image file
Returns:
bool: True if valid image
"""
try:
# Check file exists and size
if not os.path.exists(filepath):
return False
file_size = os.path.getsize(filepath)
if file_size < MIN_FILE_SIZE or file_size > MAX_FILE_SIZE:
logger.warning(f"Invalid file size: {file_size}")
return False
# Check image signature
with open(filepath, 'rb') as f:
header = f.read(12)
for signature in IMAGE_SIGNATURES:
if header.startswith(signature):
return True
return False
except Exception as e:
logger.error(f"Error validating image: {e}")
return False
def create_directory(path: Path) -> bool:
"""
Create directory if it doesn't exist
Args:
path (Path): Directory path
Returns:
bool: True if successful
"""
try:
path.mkdir(parents=True, exist_ok=True)
return True
except Exception as e:
logger.error(f"Error creating directory {path}: {e}")
return False
def clean_up_file(filepath: str) -> None:
"""
Remove file if it exists
Args:
filepath (str): Path to file to remove
"""
try:
if os.path.exists(filepath):
os.remove(filepath)
except Exception as e:
logger.error(f"Error removing file {filepath}: {e}")
def parse_json_safely(json_string: str) -> Optional[dict]:
"""
Safely parse JSON string
Args:
json_string (str): JSON string to parse
Returns:
dict or None: Parsed JSON or None if failed
"""
try:
return json.loads(json_string)
except json.JSONDecodeError:
return None
def rate_limit_delay(delay: float = 1.0) -> None:
"""
Add delay between requests to be respectful to servers
Args:
delay (float): Delay in seconds
"""
time.sleep(delay)
def format_file_size(size_bytes: int) -> str:
"""
Format file size in human readable format
Args:
size_bytes (int): Size in bytes
Returns:
str: Formatted size string
"""
if size_bytes < 1024:
return f"{size_bytes} B"
elif size_bytes < 1024 * 1024:
return f"{size_bytes / 1024:.1f} KB"
else:
return f"{size_bytes / (1024 * 1024):.1f} MB"
def truncate_text(text: str, max_length: int = 100) -> str:
"""
Truncate text to specified length
Args:
text (str): Text to truncate
max_length (int): Maximum length
Returns:
str: Truncated text
"""
if len(text) <= max_length:
return text
return text[:max_length - 3] + "..." |