Started with db development

This commit is contained in:
Jonas Linter
2025-09-27 17:35:05 +02:00
parent 7b539ea42f
commit ff00edf35d
8 changed files with 136 additions and 27 deletions

View File

@@ -2,4 +2,5 @@
from .main import main
if __name__ == "__main__":
print("running test main")
main()

View File

@@ -1,10 +1,89 @@
import os
import yaml
import annotatedyaml
from pathlib import Path
from typing import Any, Dict, List, Optional
from annotatedyaml.loader import (
HAS_C_LOADER,
JSON_TYPE,
LoaderType,
Secrets,
add_constructor,
load_yaml as load_annotated_yaml,
load_yaml_dict as load_annotated_yaml_dict,
parse_yaml as parse_annotated_yaml,
secret_yaml as annotated_secret_yaml,
)
from voluptuous import Schema, Required, All, Length, PREVENT_EXTRA, MultipleInvalid
CONFIG_PATH = os.path.join(os.path.dirname(__file__), '../../config/config.yaml')
# --- Voluptuous schemas ---
database_schema = Schema({
Required('url'): str
}, extra=PREVENT_EXTRA)
hotel_auth_schema = Schema({
Required("hotel_id"): str,
Required("hotel_name"): str,
Required("username"): str,
Required("password"): str
}, extra=PREVENT_EXTRA)
basic_auth_schema = Schema(
All([hotel_auth_schema], Length(min=1))
)
config_schema = Schema({
Required('database'): database_schema,
Required('alpine_bits_auth'): basic_auth_schema
}, extra=PREVENT_EXTRA)
DEFAULT_CONFIG_FILE = 'config.yaml'
class Config:
def __init__(self, config_folder: str | Path = None, config_name: str = DEFAULT_CONFIG_FILE, testing_mode: bool = False):
if config_folder is None:
config_folder = os.environ.get('ALPINEBITS_CONFIG_DIR')
if not config_folder:
config_folder = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../config'))
if isinstance(config_folder, str):
config_folder = Path(config_folder)
self.config_folder = config_folder
self.config_path = os.path.join(config_folder, config_name)
self.secrets = Secrets(config_folder)
self.testing_mode = testing_mode
self._load_config()
def _load_config(self):
stuff = load_annotated_yaml(self.config_path, secrets=self.secrets)
try:
validated = config_schema(stuff)
except MultipleInvalid as e:
raise ValueError(f"Config validation error: {e}")
self.database = validated['database']
self.basic_auth = validated['alpine_bits_auth']
self.config = validated
def get(self, key, default=None):
return self.config.get(key, default)
@property
def db_url(self) -> str:
return self.database['url']
@property
def hotel_id(self) -> str:
return self.basic_auth['hotel_id']
@property
def hotel_name(self) -> str:
return self.basic_auth['hotel_name']
@property
def users(self) -> List[Dict[str, str]]:
return self.basic_auth['users']
# For backward compatibility
def load_config():
with open(CONFIG_PATH, 'r', encoding='utf-8') as f:
# Use annotatedyaml to load secrets if present
return annotatedyaml.load(f)
return Config().config

View File

@@ -46,15 +46,20 @@ class HashedCustomer(Base):
redacted_at = Column(DateTime)
def get_engine():
db_url = os.environ.get('DATABASE_URL')
if db_url:
return create_engine(db_url)
# Default to local sqlite
return create_engine('sqlite:///alpinebits.db')
def get_engine(config=None):
db_url = None
if config and 'database' in config and 'url' in config['database']:
db_url = config['database']['url']
if not db_url:
db_url = os.environ.get('DATABASE_URL')
if not db_url:
db_url = 'sqlite:///alpinebits.db'
return create_engine(db_url)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=get_engine())
def get_session_local(config=None):
engine = get_engine(config)
return sessionmaker(autocommit=False, autoflush=False, bind=engine)
def init_db():
engine = get_engine()
def init_db(config=None):
engine = get_engine(config)
Base.metadata.create_all(bind=engine)

View File

@@ -18,20 +18,38 @@ from .simplified_access import (
)
# DB and config
from .db import Customer as DBCustomer, Reservation as DBReservation, HashedCustomer, SessionLocal, init_db
from .db import Customer as DBCustomer, Reservation as DBReservation, HashedCustomer, get_session_local, init_db
from .config_loader import load_config
import hashlib
import json
import os
def main():
import json
import os
print("🚀 Starting AlpineBits XML generation script...")
# Load config (yaml, annotatedyaml)
config = load_config()
# print config for debugging
print("Loaded configuration:")
print(json.dumps(config, indent=2))
# Ensure SQLite DB file exists if using SQLite
db_url = config.get('database', {}).get('url', '')
if db_url.startswith('sqlite:///'):
db_path = db_url.replace('sqlite:///', '')
db_path = os.path.abspath(db_path)
db_dir = os.path.dirname(db_path)
if not os.path.exists(db_dir):
os.makedirs(db_dir, exist_ok=True)
# The DB file will be created by SQLAlchemy if it doesn't exist, but ensure directory exists
# Init DB
init_db()
init_db(config)
print("📦 Database initialized/ready.")
SessionLocal = get_session_local(config)
db = SessionLocal()
# Load data from JSON file