refactor: split monolithic app.py into modular Flask application with factory pattern
- Created app/ package with 6 modules: - __init__.py: Application factory (create_app function) - routes.py: All route handlers (473 lines) - models.py: Data persistence layer (41 lines) - validators.py: Input validation functions (48 lines) - email_service.py: Email sending functions (85 lines) - utils.py: Utility functions (30 lines) - Implemented Flask application factory pattern - Created run.py as minimal entry point - Updated all test imports to use new module structure - Fixed template/static folder paths for package structure - All 102 tests passing - Improved maintainability with clear separation of concerns - Follows Flask best practices for scalable applications
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
"""
|
||||
Validation functions for the Flask job application system.
|
||||
"""
|
||||
import re
|
||||
from flask import current_app
|
||||
|
||||
|
||||
def validate_email(email):
|
||||
"""Validate email format"""
|
||||
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
|
||||
return re.match(pattern, email) is not None
|
||||
|
||||
|
||||
def validate_phone(phone):
|
||||
"""Validate international phone format"""
|
||||
# Accepts formats like: +41 79 123 45 67, +41791234567, etc.
|
||||
# Remove spaces and check if it matches the pattern
|
||||
pattern = r'^\+\d{1,3}[\s\d]{1,20}$'
|
||||
if not re.match(pattern, phone):
|
||||
return False
|
||||
# Ensure there are at least some digits after the country code
|
||||
digits_only = re.sub(r'\s', '', phone)
|
||||
return len(digits_only) >= 5 # At least +XX XXX format
|
||||
|
||||
|
||||
def validate_year(year):
|
||||
"""Validate birth year"""
|
||||
try:
|
||||
year_int = int(year)
|
||||
return (current_app.config['MIN_BIRTH_YEAR'] <= year_int <= current_app.config['MAX_BIRTH_YEAR']
|
||||
and len(str(year)) == 4)
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
|
||||
def validate_zip(zip_code):
|
||||
"""Validate ZIP code"""
|
||||
try:
|
||||
zip_int = int(zip_code)
|
||||
return len(str(zip_code)) <= current_app.config['MAX_ZIP_DIGITS']
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
|
||||
def allowed_file(filename):
|
||||
"""Check if file extension is allowed"""
|
||||
return '.' in filename and \
|
||||
filename.rsplit('.', 1)[1].lower() in current_app.config['ALLOWED_EXTENSIONS']
|
||||
Reference in New Issue
Block a user