diff --git a/.coverage b/.coverage new file mode 100644 index 0000000..ea75e84 Binary files /dev/null and b/.coverage differ diff --git a/.env b/.env new file mode 100644 index 0000000..f8ddecd --- /dev/null +++ b/.env @@ -0,0 +1,6 @@ +# Environment variables for development +# You can add project-specific environment variables here + +# Example: +# ALPINEBITS_CONFIG_DIR=./config +# PYTHONPATH=./src \ No newline at end of file diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index d36276a..c9a8311 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -26,6 +26,10 @@ Data flows: Wix form → Database → AlpineBits XML → Hotel systems (pull or - Default config location: `config/config.yaml` + `config/secrets.yaml` - Override via `ALPINEBITS_CONFIG_DIR` environment variable - Multi-hotel support: Each hotel in `alpine_bits_auth` array gets own credentials and optional `push_endpoint` +- **Logging**: Centralized logging configured via `logger` section (see `logging_config.py` and `LOGGING.md`) + - Use `from logging_config import get_logger; _LOGGER = get_logger(__name__)` in any module + - Logs to console always; optionally to file if `logger.file` is set + - Format includes timestamp: `%(asctime)s - %(name)s - %(levelname)s - %(message)s` ### Database Layer diff --git a/.gitignore b/.gitignore index 211c784..7fc53e2 100644 --- a/.gitignore +++ b/.gitignore @@ -19,9 +19,15 @@ test_data/* test/test_output/* +logs/* + # ignore secrets secrets.yaml # ignore db alpinebits.db + +# test output files +test_output.txt +output.xml diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..80f55a9 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,38 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Debug Tests", + "type": "debugpy", + "request": "launch", + "program": "${file}", + "purpose": [ + "debug-test" + ], + "console": "integratedTerminal", + "justMyCode": false, + "env": { + "PYTEST_ADDOPTS": "--no-cov" + } + }, + { + "name": "Python: Current File", + "type": "debugpy", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "justMyCode": true + }, + { + "name": "Python: API Server", + "type": "debugpy", + "request": "launch", + "module": "alpine_bits_python.run_api", + "console": "integratedTerminal", + "justMyCode": true, + "env": { + "ALPINEBITS_CONFIG_DIR": "${workspaceFolder}/config" + } + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 35d9ae1..42ff111 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -18,7 +18,31 @@ "notebook.output.wordWrap": true, "notebook.output.textLineLimit": 200, "jupyter.debugJustMyCode": false, + "python.defaultInterpreterPath": "./.venv/bin/python", + "python.terminal.activateEnvironment": true, + "python.terminal.activateEnvInCurrentTerminal": true, + "python.envFile": "${workspaceFolder}/.env", + "terminal.integrated.env.linux": { + "VIRTUAL_ENV": "${workspaceFolder}/.venv", + "PATH": "${workspaceFolder}/.venv/bin:${env:PATH}" + }, + "terminal.integrated.defaultProfile.linux": "bash", + "terminal.integrated.profiles.linux": { + "bash": { + "path": "bash", + "args": ["-c", "source ${workspaceFolder}/.venv/bin/activate && exec bash"] + } + }, "python.testing.pytestEnabled": true, + "python.testing.pytestArgs": [ + "tests", + "-v", + "--tb=short" + ], + "python.testing.pytestPath": "./.venv/bin/pytest", + "python.testing.unittestEnabled": false, + "python.testing.autoTestDiscoverOnSaveEnabled": true, + "python.testing.cwd": "${workspaceFolder}", "files.exclude": { "**/*.egg-info": true, "**/htmlcov": true, @@ -27,27 +51,6 @@ "**/.venv": true, "**/__pycache__": true, "**/.mypy_cache": true, - "**/.pytest_cache": true, + "**/.pytest_cache": true } -} - -// .vscode/launch.json -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Python: Debug Tests", - "type": "debugpy", - "request": "launch", - "program": "${file}", - "purpose": [ - "debug-test" - ], - "console": "integratedTerminal", - "justMyCode": false, - "env": { - "PYTEST_ADDOPTS": "--no-cov" - } - } - ] } \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..6df895a --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +This python project is managed by uv. Use uv run to execute app and tests. diff --git a/LOGGING.md b/LOGGING.md new file mode 100644 index 0000000..4ab4d47 --- /dev/null +++ b/LOGGING.md @@ -0,0 +1,118 @@ +# Logging Configuration + +The AlpineBits Python server uses a centralized logging system that can be configured via the `config.yaml` file. + +## Configuration + +Add the following section to your `config/config.yaml`: + +```yaml +logger: + level: "INFO" # Options: DEBUG, INFO, WARNING, ERROR, CRITICAL + file: "logs/alpinebits.log" # Optional: path to log file (omit or set to null for console-only) +``` + +### Log Levels + +- **DEBUG**: Detailed diagnostic information (very verbose) +- **INFO**: General informational messages about application progress +- **WARNING**: Warning messages about potential issues +- **ERROR**: Error messages when something goes wrong +- **CRITICAL**: Critical errors that may cause application failure + +### Log Output + +- **Console**: Logs are always written to console (stdout) +- **File**: Optionally write logs to a file by specifying the `file` parameter + - File logs include the same timestamp and formatting as console logs + - Log directory will be created automatically if it doesn't exist + +## Usage in Code + +To use logging in any module: + +```python +from alpine_bits_python.logging_config import get_logger + +_LOGGER = get_logger(__name__) + +# Then use the logger +_LOGGER.info("Application started") +_LOGGER.debug("Detailed debug information: %s", some_variable) +_LOGGER.warning("Something unusual happened") +_LOGGER.error("An error occurred: %s", error_message) +_LOGGER.exception("Critical error with stack trace") +``` + +## Log Format + +All log entries include: + +- Timestamp (YYYY-MM-DD HH:MM:SS) +- Module name (logger name) +- Log level +- Message + +Example: + +``` +2025-10-09 14:23:45 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-09 14:23:45 - alpine_bits_python.api - INFO - Logging configured at INFO level +2025-10-09 14:23:46 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +``` + +## Best Practices + +1. **Use structured logging**: Pass variables as arguments, not f-strings + + ```python + # Good + _LOGGER.info("Processing reservation %s for hotel %s", reservation_id, hotel_code) + + # Avoid (performance overhead, linting warnings) + _LOGGER.info(f"Processing reservation {reservation_id} for hotel {hotel_code}") + ``` + +2. **Use appropriate log levels**: + + - `DEBUG`: Detailed tracing for development + - `INFO`: Normal application flow events + - `WARNING`: Unexpected but handled situations + - `ERROR`: Errors that need attention + - `CRITICAL`: Severe errors requiring immediate action + +3. **Use `exception()` for error handling**: + + ```python + try: + risky_operation() + except Exception: + _LOGGER.exception("Operation failed") # Automatically includes stack trace + ``` + +4. **Don't log sensitive data**: Avoid logging passwords, tokens, or personal data + +## Examples + +### Console-only logging (development) + +```yaml +logger: + level: "DEBUG" +``` + +### File logging (production) + +```yaml +logger: + level: "INFO" + file: "/var/log/alpinebits/app.log" +``` + +### Minimal logging + +```yaml +logger: + level: "WARNING" + file: "logs/warnings.log" +``` diff --git a/alpinebits.log b/alpinebits.log new file mode 100644 index 0000000..a17a9b0 --- /dev/null +++ b/alpinebits.log @@ -0,0 +1,14061 @@ +2025-10-09 14:28:51 - root - INFO - Logging to file: alpinebits.log +2025-10-09 14:28:51 - root - INFO - Logging configured at INFO level +2025-10-09 14:28:51 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-09 14:28:51 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-09 14:28:51 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-09 14:28:51 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-09 14:28:51 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-09 14:28:51 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-09 14:28:51 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-09 14:28:51 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-09 14:28:51 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-09 14:28:51 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-09 16:54:04 - root - INFO - Logging to file: alpinebits.log +2025-10-09 16:54:04 - root - INFO - Logging configured at INFO level +2025-10-09 16:54:04 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-09 16:54:04 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-09 16:54:04 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-09 16:54:04 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-09 16:54:04 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-09 16:54:04 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-09 16:54:04 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-09 16:54:04 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-09 16:54:04 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-09 16:54:04 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-09 16:54:48 - root - INFO - Logging to file: alpinebits.log +2025-10-09 16:54:48 - root - INFO - Logging configured at INFO level +2025-10-09 16:54:48 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-09 16:54:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-09 16:54:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-09 16:54:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-09 16:54:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-09 16:54:48 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-09 16:54:48 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-09 16:54:48 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-09 16:54:48 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-09 16:54:48 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-09 16:54:50 - alpine_bits_python.api - INFO - AlpineBits authentication successful for user: sebastian (from config) +2025-10-09 16:54:50 - alpine_bits_python.api - INFO - Created directory: logs/conversions_import +2025-10-09 16:54:50 - alpine_bits_python.api - INFO - XML file saved to logs/conversions_import/file_sebastian_20251009_165450.xml by user sebastian (original: file.xml) +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: GET http://testserver/api/ "HTTP/1.1 200 OK" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: GET http://testserver/ "HTTP/1.1 200 OK" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:50:59.202818 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105059.json +2025-10-10 10:50:59 - alpine_bits_python.api - ERROR - Error parsing submissionTime: Invalid isoformat string: '2025-10-10T08:50:59.201813+00:0' +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 438, in process_wix_form_submission + submissionTime = datetime.fromisoformat( + submissionTime[:-1] + ) # Remove Z and convert +ValueError: Invalid isoformat string: '2025-10-10T08:50:59.201813+00:0' +2025-10-10 10:50:59 - alpine_bits_python.api - ERROR - Error in handle_wix_form: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:50:59 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:50:59.255107 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105059.json +2025-10-10 10:50:59 - alpine_bits_python.api - ERROR - Error parsing submissionTime: Invalid isoformat string: '2025-10-10T08:50:59.254048+00:0' +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 438, in process_wix_form_submission + submissionTime = datetime.fromisoformat( + submissionTime[:-1] + ) # Remove Z and convert +ValueError: Invalid isoformat string: '2025-10-10T08:50:59.254048+00:0' +2025-10-10 10:50:59 - alpine_bits_python.api - ERROR - Error in handle_wix_form: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:50:59 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:50:59.277382 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105059.json +2025-10-10 10:50:59 - alpine_bits_python.api - ERROR - Error in handle_wix_form: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:50:59 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:50:59.298832 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105059.json +2025-10-10 10:50:59 - alpine_bits_python.api - ERROR - Error parsing submissionTime: Invalid isoformat string: '2025-10-10T08:50:59.297932+00:0' +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 438, in process_wix_form_submission + submissionTime = datetime.fromisoformat( + submissionTime[:-1] + ) # Remove Z and convert +ValueError: Invalid isoformat string: '2025-10-10T08:50:59.297932+00:0' +2025-10-10 10:50:59 - alpine_bits_python.api - ERROR - Error in handle_wix_form_test: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 570, in handle_wix_form_test + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form/test "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test_reservation.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/compressed.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: PUT http://testserver/etc/passwd "HTTP/1.1 404 Not Found" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/empty.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/notxml.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:50:59.581468 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105059.json +2025-10-10 10:50:59 - alpine_bits_python.api - ERROR - Error parsing submissionTime: Invalid isoformat string: '2025-10-10T08:50:59.579944+00:0' +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 438, in process_wix_form_submission + submissionTime = datetime.fromisoformat( + submissionTime[:-1] + ) # Remove Z and convert +ValueError: Invalid isoformat string: '2025-10-10T08:50:59.579944+00:0' +2025-10-10 10:50:59 - alpine_bits_python.api - ERROR - Error in handle_wix_form: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:50:59 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 422 Unprocessable Entity" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:50:59.802241 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105059.json +2025-10-10 10:50:59 - alpine_bits_python.api - ERROR - Error in handle_wix_form: list index out of range +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +2025-10-10 10:50:59 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: OPTIONS http://testserver/api/health "HTTP/1.1 400 Bad Request" +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:50:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:50:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:50:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:50:59 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:50:59 - sqlalchemy.pool.impl.AsyncAdaptedQueuePool - ERROR - The garbage collector is trying to clean up non-checked-in connection >, which will be dropped, as it cannot be safely terminated. Please ensure that SQLAlchemy pooled connections are returned to the pool explicitly, either by calling ``close()`` or by using appropriate context managers to manage their lifecycle. +2025-10-10 10:51:10 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:10 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:10 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:10 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:10 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:10 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:10 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:10 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:10 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:10 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:10 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:10 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:10 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:51:10.201531 +2025-10-10 10:51:10 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:51:10 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:51:10 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105110.json +2025-10-10 10:51:10 - alpine_bits_python.api - ERROR - Error parsing submissionTime: Invalid isoformat string: '2025-10-10T08:51:10.200188+00:0' +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 438, in process_wix_form_submission + submissionTime = datetime.fromisoformat( + submissionTime[:-1] + ) # Remove Z and convert +ValueError: Invalid isoformat string: '2025-10-10T08:51:10.200188+00:0' +2025-10-10 10:51:10 - alpine_bits_python.api - ERROR - Error in handle_wix_form: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:51:10 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:51:10 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:51:58 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:58 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:58 - httpx - INFO - HTTP Request: GET http://testserver/api/ "HTTP/1.1 200 OK" +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:58 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:58 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:58 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:58 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:58 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:58 - httpx - INFO - HTTP Request: GET http://testserver/ "HTTP/1.1 200 OK" +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:58 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:58 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:51:58.956742 +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105158.json +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Dispatched form_processed event for hotel 123 +2025-10-10 10:51:58 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 200 OK" +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:58 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:58 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:58 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:58 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:51:59.000054 +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105159.json +2025-10-10 10:51:59 - alpine_bits_python.api - ERROR - Error in handle_wix_form: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:51:59 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:51:59.034662 +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105159.json +2025-10-10 10:51:59 - alpine_bits_python.api - ERROR - Error in handle_wix_form: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:51:59 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:51:59.054439 +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105159.json +2025-10-10 10:51:59 - alpine_bits_python.api - ERROR - Error in handle_wix_form_test: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 570, in handle_wix_form_test + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form/test "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test_reservation.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/compressed.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: PUT http://testserver/etc/passwd "HTTP/1.1 404 Not Found" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/empty.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/notxml.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:51:59.297463 +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105159.json +2025-10-10 10:51:59 - alpine_bits_python.api - ERROR - Error in handle_wix_form: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:51:59 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 422 Unprocessable Entity" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:51:59.347401 +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105159.json +2025-10-10 10:51:59 - alpine_bits_python.api - ERROR - Error in handle_wix_form: list index out of range +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +2025-10-10 10:51:59 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: OPTIONS http://testserver/api/health "HTTP/1.1 400 Bad Request" +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:51:59 - root - INFO - Logging configured at INFO level +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:51:59 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:51:59 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:51:59 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:51:59 - sqlalchemy.pool.impl.AsyncAdaptedQueuePool - ERROR - The garbage collector is trying to clean up non-checked-in connection >, which will be dropped, as it cannot be safely terminated. Please ensure that SQLAlchemy pooled connections are returned to the pool explicitly, either by calling ``close()`` or by using appropriate context managers to manage their lifecycle. +2025-10-10 10:52:16 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:16 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:16 - httpx - INFO - HTTP Request: GET http://testserver/api/ "HTTP/1.1 200 OK" +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:16 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:16 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:16 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:16 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:16 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:16 - httpx - INFO - HTTP Request: GET http://testserver/ "HTTP/1.1 200 OK" +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:16 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:16 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:52:16.887607 +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105216.json +2025-10-10 10:52:16 - alpine_bits_python.api - ERROR - Error in handle_wix_form: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:52:16 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:52:16 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:16 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:16 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:52:16.958883 +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:52:16 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105216.json +2025-10-10 10:52:16 - alpine_bits_python.api - ERROR - Error in handle_wix_form: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:52:16 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:52:16 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:16 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:17 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:52:17.009341 +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105217.json +2025-10-10 10:52:17 - alpine_bits_python.api - ERROR - Error in handle_wix_form: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:52:17 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:52:17 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:17 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:52:17.051714 +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105217.json +2025-10-10 10:52:17 - alpine_bits_python.api - ERROR - Error in handle_wix_form_test: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 570, in handle_wix_form_test + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:52:17 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form/test "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:17 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:17 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:17 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:17 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:17 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:17 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:17 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:17 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:17 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:17 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:17 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:17 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test_reservation.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:17 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:17 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/compressed.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:17 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:17 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:17 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:17 - httpx - INFO - HTTP Request: PUT http://testserver/etc/passwd "HTTP/1.1 404 Not Found" +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:17 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:17 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/empty.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:17 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:17 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/notxml.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:17 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:17 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:17 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:17 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:17 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:17 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:17 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:17 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:52:17.465784 +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:52:17 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105217.json +2025-10-10 10:52:17 - alpine_bits_python.api - ERROR - Error in handle_wix_form: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:52:17 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:18 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:18 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:18 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 422 Unprocessable Entity" +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:18 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:18 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:52:18.617919 +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105218.json +2025-10-10 10:52:18 - alpine_bits_python.api - ERROR - Error in handle_wix_form: list index out of range +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +2025-10-10 10:52:18 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +2025-10-10 10:52:18 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:18 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:18 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:18 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:18 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:18 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:18 - httpx - INFO - HTTP Request: OPTIONS http://testserver/api/health "HTTP/1.1 400 Bad Request" +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:18 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:52:18 - root - INFO - Logging configured at INFO level +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:52:18 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:52:18 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:52:18 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:52:18 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:52:18 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:52:18 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:52:18 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:52:19 - sqlalchemy.pool.impl.AsyncAdaptedQueuePool - ERROR - The garbage collector is trying to clean up non-checked-in connection >, which will be dropped, as it cannot be safely terminated. Please ensure that SQLAlchemy pooled connections are returned to the pool explicitly, either by calling ``close()`` or by using appropriate context managers to manage their lifecycle. +2025-10-10 10:53:05 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:05 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:05 - httpx - INFO - HTTP Request: GET http://testserver/api/ "HTTP/1.1 200 OK" +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:05 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:05 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:05 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:05 - httpx - INFO - HTTP Request: GET http://testserver/ "HTTP/1.1 200 OK" +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:05 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:53:05.769294 +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105305.json +2025-10-10 10:53:05 - alpine_bits_python.api - ERROR - Error in handle_wix_form: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:53:05 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:53:05 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:05 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:53:05.826369 +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105305.json +2025-10-10 10:53:05 - alpine_bits_python.api - ERROR - Error in handle_wix_form: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:53:05 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:53:05 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:05 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:53:05.860481 +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105305.json +2025-10-10 10:53:05 - alpine_bits_python.api - ERROR - Error in handle_wix_form: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:53:05 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:53:05 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:05 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:53:05.888275 +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105305.json +2025-10-10 10:53:05 - alpine_bits_python.api - ERROR - Error in handle_wix_form_test: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 570, in handle_wix_form_test + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:53:05 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form/test "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:05 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:05 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:05 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:05 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:05 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:05 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:05 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:05 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:05 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:06 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:06 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test_reservation.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:06 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/compressed.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:06 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:06 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: PUT http://testserver/etc/passwd "HTTP/1.1 404 Not Found" +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:06 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/empty.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:06 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/notxml.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:06 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:06 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:06 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:06 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:53:06.196901 +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105306.json +2025-10-10 10:53:06 - alpine_bits_python.api - ERROR - Error in handle_wix_form: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:53:06 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:06 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 422 Unprocessable Entity" +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:06 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:53:06.622362 +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105306.json +2025-10-10 10:53:06 - alpine_bits_python.api - ERROR - Error in handle_wix_form: list index out of range +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +2025-10-10 10:53:06 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:06 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:06 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: OPTIONS http://testserver/api/health "HTTP/1.1 400 Bad Request" +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:53:06 - root - INFO - Logging configured at INFO level +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:53:06 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:53:06 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:53:06 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:53:06 - sqlalchemy.pool.impl.AsyncAdaptedQueuePool - ERROR - The garbage collector is trying to clean up non-checked-in connection >, which will be dropped, as it cannot be safely terminated. Please ensure that SQLAlchemy pooled connections are returned to the pool explicitly, either by calling ``close()`` or by using appropriate context managers to manage their lifecycle. +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: GET http://testserver/api/ "HTTP/1.1 200 OK" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: GET http://testserver/ "HTTP/1.1 200 OK" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:54:02.073375 +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105402.json +2025-10-10 10:54:02 - alpine_bits_python.api - ERROR - Error in handle_wix_form: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:54:02 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:54:02.140593 +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105402.json +2025-10-10 10:54:02 - alpine_bits_python.api - ERROR - Error in handle_wix_form: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:54:02 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:54:02.176251 +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105402.json +2025-10-10 10:54:02 - alpine_bits_python.api - ERROR - Error in handle_wix_form: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:54:02 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 445, in process_wix_form_submission + reservation = ReservationData( + unique_id=unique_id, + ...<16 lines>... + gclid=data.get("field:gclid"), + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) +pydantic_core._pydantic_core.ValidationError: 1 validation error for ReservationData +created_at + Input should be a valid datetime [type=datetime_type, input_value=None, input_type=NoneType] + For further information visit https://errors.pydantic.dev/2.11/v/datetime_type +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:54:02.206091 +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105402.json +2025-10-10 10:54:02 - alpine_bits_python.api - ERROR - Error in handle_wix_form_test: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 570, in handle_wix_form_test + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form/test "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test_reservation.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/compressed.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: PUT http://testserver/etc/passwd "HTTP/1.1 404 Not Found" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/empty.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/notxml.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:54:02.527423 +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:54:02 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105402.json +2025-10-10 10:54:02 - alpine_bits_python.api - ERROR - Error in handle_wix_form: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:54:02 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:03 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:03 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:03 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 422 Unprocessable Entity" +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:03 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:03 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:54:03.041180 +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105403.json +2025-10-10 10:54:03 - alpine_bits_python.api - ERROR - Error in handle_wix_form: list index out of range +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +2025-10-10 10:54:03 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +2025-10-10 10:54:03 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:03 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:03 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:03 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:03 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:03 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:03 - httpx - INFO - HTTP Request: OPTIONS http://testserver/api/health "HTTP/1.1 400 Bad Request" +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:03 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:54:03 - root - INFO - Logging configured at INFO level +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:54:03 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:54:03 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:54:03 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:54:03 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:54:03 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:54:03 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:54:03 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:54:03 - sqlalchemy.pool.impl.AsyncAdaptedQueuePool - ERROR - The garbage collector is trying to clean up non-checked-in connection >, which will be dropped, as it cannot be safely terminated. Please ensure that SQLAlchemy pooled connections are returned to the pool explicitly, either by calling ``close()`` or by using appropriate context managers to manage their lifecycle. +2025-10-10 10:55:48 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:55:48 - root - INFO - Logging configured at INFO level +2025-10-10 10:55:48 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:55:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:55:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:55:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:55:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:55:48 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:55:48 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:55:48 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:55:48 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:55:48 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:55:48 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:55:48.071139 +2025-10-10 10:55:48 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:55:48 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:55:48 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105548.json +2025-10-10 10:55:48 - alpine_bits_python.api - ERROR - Error in handle_wix_form: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:55:48 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:55:48 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:55:55 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:55:55 - root - INFO - Logging configured at INFO level +2025-10-10 10:55:55 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:55:55 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:55:55 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:55:55 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:55:55 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:55:55 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:55:55 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:55:55 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:55:55 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:55:55 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:55:55 - httpx - INFO - HTTP Request: GET http://testserver/api/ "HTTP/1.1 200 OK" +2025-10-10 10:55:55 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:55:55 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:55:55 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:55:55 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:55:55 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:55:55 - root - INFO - Logging configured at INFO level +2025-10-10 10:55:55 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:55:55 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:55:55 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:55:55 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:55:55 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:55:55 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:55:55 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:55:55 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:55:55 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:55:55 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:55:55 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:55:55.423973 +2025-10-10 10:55:55 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:55:55 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:55:55 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105555.json +2025-10-10 10:55:55 - alpine_bits_python.api - ERROR - Error in handle_wix_form: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:55:55 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:55:55 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:56:02 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:56:02 - root - INFO - Logging configured at INFO level +2025-10-10 10:56:02 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:56:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:56:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:56:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:56:02 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:56:02 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:56:02 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:56:02 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:56:02 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:56:02 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:56:02 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:56:02.594297 +2025-10-10 10:56:02 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:56:02 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:56:02 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105602.json +2025-10-10 10:56:02 - alpine_bits_python.api - ERROR - Error in handle_wix_form: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:56:02 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: customers.contact_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 416, in process_wix_form_submission + await db.flush() # This assigns db_customer.id without committing + ^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 801, in flush + await greenlet_spawn(self.sync_session.flush, objects=objects) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: customers.contact_id +[SQL: INSERT INTO customers (given_name, contact_id, surname, name_prefix, email_address, phone, email_newsletter, address_line, city_name, postal_code, country_code, gender, birth_date, language, address_catalog, name_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: ('John', 'contact-123', 'Doe', 'Mr.', 'john.doe@example.com', '+1234567890', 1, None, None, None, None, None, None, 'en', 0, None)] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:56:02 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:57:00 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:00 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:00 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:00 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:00 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:00 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:00.937001 +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105700.json +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Dispatched form_processed event for hotel 123 +2025-10-10 10:57:00 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 200 OK" +2025-10-10 10:57:00 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:00 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:00 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:00 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:00 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:00 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:00 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:00 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:00 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:00 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:00.970096 +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105700.json +2025-10-10 10:57:00 - alpine_bits_python.api - INFO - Dispatched form_processed event for hotel 123 +2025-10-10 10:57:00 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 200 OK" +2025-10-10 10:57:01 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:01 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:01 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:01 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:01 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:01 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:01 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:01 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:01 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:01 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:01.040061 +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105701.json +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Dispatched form_processed event for hotel 123 +2025-10-10 10:57:01 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 200 OK" +2025-10-10 10:57:01 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:01 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:01 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:01 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:01 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:01 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:01 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:01 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:01 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:01 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:01.056633 +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105701.json +2025-10-10 10:57:01 - alpine_bits_python.api - INFO - Dispatched form_processed event for hotel 123 +2025-10-10 10:57:01 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form/test "HTTP/1.1 200 OK" +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: GET http://testserver/api/ "HTTP/1.1 200 OK" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: GET http://testserver/ "HTTP/1.1 200 OK" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:07.501948 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105707.json +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Dispatched form_processed event for hotel 123 +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 200 OK" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:07.540376 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105707.json +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Dispatched form_processed event for hotel 123 +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 200 OK" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:07.562981 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105707.json +2025-10-10 10:57:07 - alpine_bits_python.api - ERROR - Error in handle_wix_form: (sqlite3.IntegrityError) UNIQUE constraint failed: reservations.md5_unique_id +[SQL: INSERT INTO reservations (customer_id, unique_id, md5_unique_id, start_date, end_date, num_adults, num_children, children_ages, offer, created_at, utm_source, utm_medium, utm_campaign, utm_term, utm_content, user_comment, fbclid, gclid, hotel_code, hotel_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: (8, 'minimal-123', '2d316901028b3c2a906a20b8dcb57261', '2025-01-15', '2025-01-20', 2, 0, '', None, '2025-01-10 12:00:00.000000', None, None, None, None, None, '', None, None, '123', 'Frangart Inn')] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: reservations.md5_unique_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 471, in process_wix_form_submission + await db.commit() + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 1014, in commit + await greenlet_spawn(self.sync_session.commit) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 2032, in commit + trans.commit(_to_root=True) + ~~~~~~~~~~~~^^^^^^^^^^^^^^^ + File "", line 2, in commit + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1313, in commit + self._prepare_impl() + ~~~~~~~~~~~~~~~~~~^^ + File "", line 2, in _prepare_impl + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1288, in _prepare_impl + self.session.flush() + ~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: reservations.md5_unique_id +[SQL: INSERT INTO reservations (customer_id, unique_id, md5_unique_id, start_date, end_date, num_adults, num_children, children_ages, offer, created_at, utm_source, utm_medium, utm_campaign, utm_term, utm_content, user_comment, fbclid, gclid, hotel_code, hotel_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: (8, 'minimal-123', '2d316901028b3c2a906a20b8dcb57261', '2025-01-15', '2025-01-20', 2, 0, '', None, '2025-01-10 12:00:00.000000', None, None, None, None, None, '', None, None, '123', 'Frangart Inn')] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:57:07 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: reservations.md5_unique_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 471, in process_wix_form_submission + await db.commit() + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 1014, in commit + await greenlet_spawn(self.sync_session.commit) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 2032, in commit + trans.commit(_to_root=True) + ~~~~~~~~~~~~^^^^^^^^^^^^^^^ + File "", line 2, in commit + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1313, in commit + self._prepare_impl() + ~~~~~~~~~~~~~~~~~~^^ + File "", line 2, in _prepare_impl + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1288, in _prepare_impl + self.session.flush() + ~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: reservations.md5_unique_id +[SQL: INSERT INTO reservations (customer_id, unique_id, md5_unique_id, start_date, end_date, num_adults, num_children, children_ages, offer, created_at, utm_source, utm_medium, utm_campaign, utm_term, utm_content, user_comment, fbclid, gclid, hotel_code, hotel_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: (8, 'minimal-123', '2d316901028b3c2a906a20b8dcb57261', '2025-01-15', '2025-01-20', 2, 0, '', None, '2025-01-10 12:00:00.000000', None, None, None, None, None, '', None, None, '123', 'Frangart Inn')] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: reservations.md5_unique_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 471, in process_wix_form_submission + await db.commit() + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 1014, in commit + await greenlet_spawn(self.sync_session.commit) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 2032, in commit + trans.commit(_to_root=True) + ~~~~~~~~~~~~^^^^^^^^^^^^^^^ + File "", line 2, in commit + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1313, in commit + self._prepare_impl() + ~~~~~~~~~~~~~~~~~~^^ + File "", line 2, in _prepare_impl + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1288, in _prepare_impl + self.session.flush() + ~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: reservations.md5_unique_id +[SQL: INSERT INTO reservations (customer_id, unique_id, md5_unique_id, start_date, end_date, num_adults, num_children, children_ages, offer, created_at, utm_source, utm_medium, utm_campaign, utm_term, utm_content, user_comment, fbclid, gclid, hotel_code, hotel_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: (8, 'minimal-123', '2d316901028b3c2a906a20b8dcb57261', '2025-01-15', '2025-01-20', 2, 0, '', None, '2025-01-10 12:00:00.000000', None, None, None, None, None, '', None, None, '123', 'Frangart Inn')] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:07.595200 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105707.json +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Dispatched form_processed event for hotel 123 +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form/test "HTTP/1.1 200 OK" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test_reservation.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/compressed.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: PUT http://testserver/etc/passwd "HTTP/1.1 404 Not Found" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/empty.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/notxml.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:07.737177 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105707.json +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 422 Unprocessable Entity" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:07.763631 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105707.json +2025-10-10 10:57:07 - alpine_bits_python.api - ERROR - Error in handle_wix_form: list index out of range +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +2025-10-10 10:57:07 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: OPTIONS http://testserver/api/health "HTTP/1.1 400 Bad Request" +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:07 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:07 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:07 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:07 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:07 - sqlalchemy.pool.impl.AsyncAdaptedQueuePool - ERROR - The garbage collector is trying to clean up non-checked-in connection >, which will be dropped, as it cannot be safely terminated. Please ensure that SQLAlchemy pooled connections are returned to the pool explicitly, either by calling ``close()`` or by using appropriate context managers to manage their lifecycle. +2025-10-10 10:57:14 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:14 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:14 - httpx - INFO - HTTP Request: GET http://testserver/api/ "HTTP/1.1 200 OK" +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:14 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:14 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:14 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:14 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:14 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:14 - httpx - INFO - HTTP Request: GET http://testserver/ "HTTP/1.1 200 OK" +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:14 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:14 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:14.871642 +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105714.json +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Dispatched form_processed event for hotel 123 +2025-10-10 10:57:14 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 200 OK" +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:14 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:14 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:14 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:14.931247 +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105714.json +2025-10-10 10:57:14 - alpine_bits_python.api - INFO - Dispatched form_processed event for hotel 123 +2025-10-10 10:57:14 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 200 OK" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:15.031197 +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105715.json +2025-10-10 10:57:15 - alpine_bits_python.api - ERROR - Error in handle_wix_form: (sqlite3.IntegrityError) UNIQUE constraint failed: reservations.md5_unique_id +[SQL: INSERT INTO reservations (customer_id, unique_id, md5_unique_id, start_date, end_date, num_adults, num_children, children_ages, offer, created_at, utm_source, utm_medium, utm_campaign, utm_term, utm_content, user_comment, fbclid, gclid, hotel_code, hotel_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: (12, 'minimal-123', '2d316901028b3c2a906a20b8dcb57261', '2025-01-15', '2025-01-20', 2, 0, '', None, '2025-01-10 12:00:00.000000', None, None, None, None, None, '', None, None, '123', 'Frangart Inn')] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: reservations.md5_unique_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 471, in process_wix_form_submission + await db.commit() + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 1014, in commit + await greenlet_spawn(self.sync_session.commit) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 2032, in commit + trans.commit(_to_root=True) + ~~~~~~~~~~~~^^^^^^^^^^^^^^^ + File "", line 2, in commit + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1313, in commit + self._prepare_impl() + ~~~~~~~~~~~~~~~~~~^^ + File "", line 2, in _prepare_impl + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1288, in _prepare_impl + self.session.flush() + ~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: reservations.md5_unique_id +[SQL: INSERT INTO reservations (customer_id, unique_id, md5_unique_id, start_date, end_date, num_adults, num_children, children_ages, offer, created_at, utm_source, utm_medium, utm_campaign, utm_term, utm_content, user_comment, fbclid, gclid, hotel_code, hotel_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: (12, 'minimal-123', '2d316901028b3c2a906a20b8dcb57261', '2025-01-15', '2025-01-20', 2, 0, '', None, '2025-01-10 12:00:00.000000', None, None, None, None, None, '', None, None, '123', 'Frangart Inn')] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:57:15 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: reservations.md5_unique_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 471, in process_wix_form_submission + await db.commit() + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 1014, in commit + await greenlet_spawn(self.sync_session.commit) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 2032, in commit + trans.commit(_to_root=True) + ~~~~~~~~~~~~^^^^^^^^^^^^^^^ + File "", line 2, in commit + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1313, in commit + self._prepare_impl() + ~~~~~~~~~~~~~~~~~~^^ + File "", line 2, in _prepare_impl + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1288, in _prepare_impl + self.session.flush() + ~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: reservations.md5_unique_id +[SQL: INSERT INTO reservations (customer_id, unique_id, md5_unique_id, start_date, end_date, num_adults, num_children, children_ages, offer, created_at, utm_source, utm_medium, utm_campaign, utm_term, utm_content, user_comment, fbclid, gclid, hotel_code, hotel_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: (12, 'minimal-123', '2d316901028b3c2a906a20b8dcb57261', '2025-01-15', '2025-01-20', 2, 0, '', None, '2025-01-10 12:00:00.000000', None, None, None, None, None, '', None, None, '123', 'Frangart Inn')] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: reservations.md5_unique_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 471, in process_wix_form_submission + await db.commit() + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 1014, in commit + await greenlet_spawn(self.sync_session.commit) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 2032, in commit + trans.commit(_to_root=True) + ~~~~~~~~~~~~^^^^^^^^^^^^^^^ + File "", line 2, in commit + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1313, in commit + self._prepare_impl() + ~~~~~~~~~~~~~~~~~~^^ + File "", line 2, in _prepare_impl + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1288, in _prepare_impl + self.session.flush() + ~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: reservations.md5_unique_id +[SQL: INSERT INTO reservations (customer_id, unique_id, md5_unique_id, start_date, end_date, num_adults, num_children, children_ages, offer, created_at, utm_source, utm_medium, utm_campaign, utm_term, utm_content, user_comment, fbclid, gclid, hotel_code, hotel_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: (12, 'minimal-123', '2d316901028b3c2a906a20b8dcb57261', '2025-01-15', '2025-01-20', 2, 0, '', None, '2025-01-10 12:00:00.000000', None, None, None, None, None, '', None, None, '123', 'Frangart Inn')] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:15.075651 +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105715.json +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Dispatched form_processed event for hotel 123 +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form/test "HTTP/1.1 200 OK" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test_reservation.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/compressed.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: PUT http://testserver/etc/passwd "HTTP/1.1 404 Not Found" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/empty.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/notxml.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:15.391258 +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105715.json +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 422 Unprocessable Entity" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:15.857786 +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105715.json +2025-10-10 10:57:15 - alpine_bits_python.api - ERROR - Error in handle_wix_form: list index out of range +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +2025-10-10 10:57:15 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: OPTIONS http://testserver/api/health "HTTP/1.1 400 Bad Request" +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:15 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:15 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:15 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:15 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:15 - sqlalchemy.pool.impl.AsyncAdaptedQueuePool - ERROR - The garbage collector is trying to clean up non-checked-in connection >, which will be dropped, as it cannot be safely terminated. Please ensure that SQLAlchemy pooled connections are returned to the pool explicitly, either by calling ``close()`` or by using appropriate context managers to manage their lifecycle. +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: GET http://testserver/api/ "HTTP/1.1 200 OK" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: GET http://testserver/ "HTTP/1.1 200 OK" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:47.451294 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105747.json +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Dispatched form_processed event for hotel 123 +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 200 OK" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:47.488525 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105747.json +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Dispatched form_processed event for hotel 123 +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 200 OK" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:47.557385 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105747.json +2025-10-10 10:57:47 - alpine_bits_python.api - ERROR - Error in handle_wix_form: (sqlite3.IntegrityError) UNIQUE constraint failed: reservations.md5_unique_id +[SQL: INSERT INTO reservations (customer_id, unique_id, md5_unique_id, start_date, end_date, num_adults, num_children, children_ages, offer, created_at, utm_source, utm_medium, utm_campaign, utm_term, utm_content, user_comment, fbclid, gclid, hotel_code, hotel_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: (16, 'minimal-123', '2d316901028b3c2a906a20b8dcb57261', '2025-01-15', '2025-01-20', 2, 0, '', None, '2025-01-10 12:00:00.000000', None, None, None, None, None, '', None, None, '123', 'Frangart Inn')] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: reservations.md5_unique_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 471, in process_wix_form_submission + await db.commit() + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 1014, in commit + await greenlet_spawn(self.sync_session.commit) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 2032, in commit + trans.commit(_to_root=True) + ~~~~~~~~~~~~^^^^^^^^^^^^^^^ + File "", line 2, in commit + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1313, in commit + self._prepare_impl() + ~~~~~~~~~~~~~~~~~~^^ + File "", line 2, in _prepare_impl + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1288, in _prepare_impl + self.session.flush() + ~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: reservations.md5_unique_id +[SQL: INSERT INTO reservations (customer_id, unique_id, md5_unique_id, start_date, end_date, num_adults, num_children, children_ages, offer, created_at, utm_source, utm_medium, utm_campaign, utm_term, utm_content, user_comment, fbclid, gclid, hotel_code, hotel_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: (16, 'minimal-123', '2d316901028b3c2a906a20b8dcb57261', '2025-01-15', '2025-01-20', 2, 0, '', None, '2025-01-10 12:00:00.000000', None, None, None, None, None, '', None, None, '123', 'Frangart Inn')] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:57:47 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: reservations.md5_unique_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 471, in process_wix_form_submission + await db.commit() + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 1014, in commit + await greenlet_spawn(self.sync_session.commit) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 2032, in commit + trans.commit(_to_root=True) + ~~~~~~~~~~~~^^^^^^^^^^^^^^^ + File "", line 2, in commit + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1313, in commit + self._prepare_impl() + ~~~~~~~~~~~~~~~~~~^^ + File "", line 2, in _prepare_impl + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1288, in _prepare_impl + self.session.flush() + ~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: reservations.md5_unique_id +[SQL: INSERT INTO reservations (customer_id, unique_id, md5_unique_id, start_date, end_date, num_adults, num_children, children_ages, offer, created_at, utm_source, utm_medium, utm_campaign, utm_term, utm_content, user_comment, fbclid, gclid, hotel_code, hotel_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: (16, 'minimal-123', '2d316901028b3c2a906a20b8dcb57261', '2025-01-15', '2025-01-20', 2, 0, '', None, '2025-01-10 12:00:00.000000', None, None, None, None, None, '', None, None, '123', 'Frangart Inn')] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlite3.IntegrityError: UNIQUE constraint failed: reservations.md5_unique_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 471, in process_wix_form_submission + await db.commit() + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/session.py", line 1014, in commit + await greenlet_spawn(self.sync_session.commit) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 203, in greenlet_spawn + result = context.switch(value) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 2032, in commit + trans.commit(_to_root=True) + ~~~~~~~~~~~~^^^^^^^^^^^^^^^ + File "", line 2, in commit + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1313, in commit + self._prepare_impl() + ~~~~~~~~~~~~~~~~~~^^ + File "", line 2, in _prepare_impl + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go + ret_value = fn(self, *arg, **kw) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1288, in _prepare_impl + self.session.flush() + ~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4345, in flush + self._flush(objects) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4480, in _flush + with util.safe_reraise(): + ~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4441, in _flush + flush_context.execute() + ~~~~~~~~~~~~~~~~~~~~~^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute + rec.execute(self) + ~~~~~~~~~~~^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute + util.preloaded.orm_persistence.save_obj( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self.mapper, + ^^^^^^^^^^^^ + uow.states_for_mapper_hierarchy(self.mapper, False, False), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + uow, + ^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj + _emit_insert_statements( + ~~~~~~~~~~~~~~~~~~~~~~~^ + base_mapper, + ^^^^^^^^^^^^ + ...<3 lines>... + insert, + ^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1233, in _emit_insert_statements + result = connection.execute( + statement, + params, + execution_options=execution_options, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute + return meth( + self, + distilled_parameters, + execution_options or NO_OPTIONS, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection + return connection._execute_clauseelement( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + self, distilled_params, execution_options + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement + ret = self._execute_context( + dialect, + ...<8 lines>... + cache_hit=cache_hit, + ) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context + return self._exec_single_context( + ~~~~~~~~~~~~~~~~~~~~~~~~~^ + dialect, context, statement, parameters + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context + self._handle_dbapi_exception( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + e, str_statement, effective_parameters, cursor, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception + raise sqlalchemy_exception.with_traceback(exc_info[2]) from e + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context + self.dialect.do_execute( + ~~~~~~~~~~~~~~~~~~~~~~~^ + cursor, str_statement, effective_parameters, context + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute + cursor.execute(statement, parameters) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 177, in execute + self._adapt_connection._handle_exception(error) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 337, in _handle_exception + raise error + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 159, in execute + self.await_(_cursor.execute(operation, parameters)) + ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 40, in execute + await self._execute(self._cursor.execute, sql, parameters) + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/cursor.py", line 32, in _execute + return await self._conn._execute(fn, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute + return await future + ^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run + result = function() +sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: reservations.md5_unique_id +[SQL: INSERT INTO reservations (customer_id, unique_id, md5_unique_id, start_date, end_date, num_adults, num_children, children_ages, offer, created_at, utm_source, utm_medium, utm_campaign, utm_term, utm_content, user_comment, fbclid, gclid, hotel_code, hotel_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] +[parameters: (16, 'minimal-123', '2d316901028b3c2a906a20b8dcb57261', '2025-01-15', '2025-01-20', 2, 0, '', None, '2025-01-10 12:00:00.000000', None, None, None, None, None, '', None, None, '123', 'Frangart Inn')] +(Background on this error at: https://sqlalche.me/e/20/gkpj) +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:47.588411 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105747.json +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Dispatched form_processed event for hotel 123 +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form/test "HTTP/1.1 200 OK" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test_reservation.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/compressed.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: PUT http://testserver/etc/passwd "HTTP/1.1 404 Not Found" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/empty.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/notxml.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:47.806604 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105747.json +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 422 Unprocessable Entity" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:47 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Received Wix form data at 2025-10-10T10:57:47.995552 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Created file owner: uid:1000, gid:1000 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - File mode: 644 +2025-10-10 10:57:47 - alpine_bits_python.api - INFO - Data logged to: logs/wix_test_data_20251010_105747.json +2025-10-10 10:57:47 - alpine_bits_python.api - ERROR - Error in handle_wix_form: list index out of range +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +2025-10-10 10:57:47 - alpine_bits_python.api - ERROR - Stack trace for handle_wix_form: Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +Traceback (most recent call last): + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 549, in handle_wix_form + return await process_wix_form_submission(request, data, db_session) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/divusjulius/repos/alpinebits_python/src/alpine_bits_python/api.py", line 367, in process_wix_form_submission + or data.get("submissions", [{}])[1].get("value") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ +IndexError: list index out of range +2025-10-10 10:57:47 - httpx - INFO - HTTP Request: POST http://testserver/api/webhook/wix-form "HTTP/1.1 500 Internal Server Error" +2025-10-10 10:57:47 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:48 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:48 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:48 - httpx - INFO - HTTP Request: POST http://testserver/api/alpinebits/server-2024-10 "HTTP/1.1 401 Unauthorized" +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:48 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:48 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:48 - httpx - INFO - HTTP Request: OPTIONS http://testserver/api/health "HTTP/1.1 400 Bad Request" +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:48 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:57:48 - root - INFO - Logging configured at INFO level +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:57:48 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:57:48 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:57:48 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:48 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:48 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:48 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:48 - httpx - INFO - HTTP Request: GET http://testserver/api/health "HTTP/1.1 200 OK" +2025-10-10 10:57:48 - sqlalchemy.pool.impl.AsyncAdaptedQueuePool - ERROR - The garbage collector is trying to clean up non-checked-in connection >, which will be dropped, as it cannot be safely terminated. Please ensure that SQLAlchemy pooled connections are returned to the pool explicitly, either by calling ``close()`` or by using appropriate context managers to manage their lifecycle. +2025-10-10 10:59:24 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:59:24 - root - INFO - Logging configured at INFO level +2025-10-10 10:59:24 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:59:24 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:59:24 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:59:24 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:59:24 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:59:24 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:59:24 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:59:24 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:59:24 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:59:24 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:59:24 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test_reservation.xml "HTTP/1.1 401 Unauthorized" +2025-10-10 10:59:53 - root - INFO - Logging to file: alpinebits.log +2025-10-10 10:59:53 - root - INFO - Logging configured at INFO level +2025-10-10 10:59:53 - alpine_bits_python.api - INFO - Application startup initiated +2025-10-10 10:59:53 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT +2025-10-10 10:59:53 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_PING +2025-10-10 10:59:53 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS +2025-10-10 10:59:53 - alpine_bits_python.alpinebits_server - INFO - Initializing action instance for AlpineBitsActionName.OTA_READ +2025-10-10 10:59:53 - alpine_bits_python.api - INFO - Hotel 39054_001 has no push_endpoint configured +2025-10-10 10:59:53 - alpine_bits_python.api - INFO - Hotel 135 has no push_endpoint configured +2025-10-10 10:59:53 - alpine_bits_python.api - INFO - Hotel 39052_001 has no push_endpoint configured +2025-10-10 10:59:53 - alpine_bits_python.api - INFO - Hotel 39040_001 has no push_endpoint configured +2025-10-10 10:59:53 - alpine_bits_python.api - INFO - Database tables checked/created at startup. +2025-10-10 10:59:53 - httpx - INFO - HTTP Request: PUT http://testserver/api/hoteldata/conversions_import/test_reservation.xml "HTTP/1.1 401 Unauthorized" diff --git a/config/config.yaml b/config/config.yaml index c95ccfc..048c7b8 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -8,6 +8,18 @@ database: # AlpineBits Python config # Use annotatedyaml for secrets and environment-specific overrides +server: + codecontext: "ADVERTISING" + code: 70597314 + companyname: "99tales Gmbh" + res_id_source_context: "99tales" + + + +logger: + level: "INFO" # Set to DEBUG for more verbose output + file: "alpinebits.log" # Log file path, or null for console only + alpine_bits_auth: - hotel_id: "39054_001" hotel_name: "Bemelmans Post" diff --git a/conftest.py b/conftest.py new file mode 100644 index 0000000..81266b7 --- /dev/null +++ b/conftest.py @@ -0,0 +1,13 @@ +"""Pytest configuration and path setup for VS Code. + +This configuration file ensures that VS Code can properly discover and run tests +by setting up the Python path to include the src directory. +""" + +import sys +from pathlib import Path + +# Add the src directory to Python path for VS Code test discovery +src_path = Path(__file__).parent / "src" +if str(src_path) not in sys.path: + sys.path.insert(0, str(src_path)) diff --git a/coverage.json b/coverage.json new file mode 100644 index 0000000..6c053d1 --- /dev/null +++ b/coverage.json @@ -0,0 +1 @@ +{"meta": {"format": 3, "version": "7.10.7", "timestamp": "2025-10-10T10:47:41.787133", "branch_coverage": false, "show_contexts": false}, "files": {"src/alpine_bits_python/__init__.py": {"executed_lines": [1], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": [], "functions": {"": {"executed_lines": [1], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"": {"executed_lines": [1], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "src/alpine_bits_python/alpine_bits_helpers.py": {"executed_lines": [1, 2, 3, 4, 5, 7, 8, 9, 19, 28, 31, 32, 35, 36, 39, 42, 45, 48, 53, 56, 60, 61, 63, 66, 70, 71, 73, 74, 76, 80, 81, 82, 85, 86, 87, 89, 92, 93, 95, 96, 107, 108, 117, 118, 128, 129, 130, 131, 132, 134, 136, 137, 140, 142, 143, 144, 147, 148, 150, 151, 153, 155, 156, 158, 160, 161, 166, 174, 175, 176, 180, 183, 184, 185, 186, 187, 189, 192, 193, 196, 197, 198, 202, 203, 204, 206, 215, 225, 226, 228, 230, 231, 233, 235, 236, 239, 240, 241, 254, 255, 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, 269, 271, 272, 273, 274, 276, 277, 279, 280, 281, 282, 283, 285, 304, 305, 307, 308, 312, 316, 317, 321, 325, 326, 330, 337, 338, 342, 346, 347, 351, 355, 356, 360, 368, 369, 371, 372, 376, 377, 379, 381, 382, 388, 389, 391, 392, 408, 411, 414, 416, 417, 421, 422, 426, 427, 449, 450, 453, 454, 456, 457, 459, 463, 464, 466, 470, 471, 478, 481, 486, 489, 492, 495, 497, 498, 503, 506, 507, 508, 511, 512, 514, 515, 529, 530, 531, 532, 534, 535, 536, 537, 539, 540, 542, 544, 546, 547, 560, 561, 562, 564, 565, 578, 579, 580, 581, 582, 585, 586, 587, 588, 589, 592, 599, 600, 603, 607, 611, 614, 621, 627, 631, 648, 649, 652, 653, 657, 662, 663, 664, 665, 666, 670, 673, 676, 680, 684, 688, 689, 691, 692, 693, 699, 700, 708, 710, 717, 718, 722, 724, 725, 727, 733, 734, 735, 746, 747, 748, 759, 762, 764, 765, 766, 767, 774, 775, 777, 778, 779, 781, 785, 787, 791, 793, 795, 797, 804, 815, 824, 828, 831, 832, 838, 839, 843, 845, 846, 851, 853, 869, 870, 874, 878, 879, 884], "summary": {"covered_lines": 299, "num_statements": 346, "percent_covered": 86.41618497109826, "percent_covered_display": "86", "missing_lines": 47, "excluded_lines": 0}, "missing_lines": [111, 112, 115, 138, 374, 393, 400, 405, 419, 424, 429, 430, 432, 433, 434, 435, 443, 445, 541, 593, 594, 595, 596, 604, 618, 658, 659, 660, 661, 668, 694, 695, 696, 723, 829, 854, 858, 862, 863, 864, 865, 866, 868, 880, 881, 882, 886], "excluded_lines": [], "functions": {"GuestCountsFactory.create_guest_counts": {"executed_lines": [107, 108], "summary": {"covered_lines": 2, "num_statements": 5, "percent_covered": 40.0, "percent_covered_display": "40", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [111, 112, 115], "excluded_lines": []}, "GuestCountsFactory._create_guest_counts": {"executed_lines": [128, 129, 130, 131, 132, 134, 136, 137, 140, 142, 143, 144], "summary": {"covered_lines": 12, "num_statements": 13, "percent_covered": 92.3076923076923, "percent_covered_display": "92", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [138], "excluded_lines": []}, "CustomerFactory.create_notif_customer": {"executed_lines": [153], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "CustomerFactory.create_retrieve_customer": {"executed_lines": [158], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "CustomerFactory._create_customer": {"executed_lines": [166, 174, 175, 176, 180, 183, 184, 185, 186, 187, 189, 192, 193, 196, 197, 198, 202, 203, 204, 206, 215], "summary": {"covered_lines": 21, "num_statements": 21, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "CustomerFactory.from_notif_customer": {"executed_lines": [228], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "CustomerFactory.from_retrieve_customer": {"executed_lines": [233], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "CustomerFactory._customer_to_data": {"executed_lines": [239, 240, 241, 254, 255, 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, 269, 271, 272, 273, 274, 276, 277, 279, 280, 281, 282, 283, 285], "summary": {"covered_lines": 29, "num_statements": 29, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "HotelReservationIdFactory.create_notif_hotel_reservation_id": {"executed_lines": [312], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "HotelReservationIdFactory.create_retrieve_hotel_reservation_id": {"executed_lines": [321], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "HotelReservationIdFactory._create_hotel_reservation_id": {"executed_lines": [330], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "HotelReservationIdFactory.from_notif_hotel_reservation_id": {"executed_lines": [342], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "HotelReservationIdFactory.from_retrieve_hotel_reservation_id": {"executed_lines": [351], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "HotelReservationIdFactory._hotel_reservation_id_to_data": {"executed_lines": [360], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "CommentFactory.create_notif_comments": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [374], "excluded_lines": []}, "CommentFactory.create_retrieve_comments": {"executed_lines": [379], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "CommentFactory._create_comments": {"executed_lines": [388, 389, 391, 392, 408, 411, 414], "summary": {"covered_lines": 7, "num_statements": 10, "percent_covered": 70.0, "percent_covered_display": "70", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [393, 400, 405], "excluded_lines": []}, "CommentFactory.from_notif_comments": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [419], "excluded_lines": []}, "CommentFactory.from_retrieve_comments": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [424], "excluded_lines": []}, "CommentFactory._comments_to_data": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 8, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 8, "excluded_lines": 0}, "missing_lines": [429, 430, 432, 433, 434, 435, 443, 445], "excluded_lines": []}, "ResGuestFactory.create_notif_res_guests": {"executed_lines": [459], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ResGuestFactory.create_retrieve_res_guests": {"executed_lines": [466], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ResGuestFactory._create_res_guests": {"executed_lines": [478, 481, 486, 489, 492, 495], "summary": {"covered_lines": 6, "num_statements": 6, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ResGuestFactory.extract_primary_customer": {"executed_lines": [503, 506, 507, 508], "summary": {"covered_lines": 4, "num_statements": 4, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "AlpineBitsFactory.create": {"executed_lines": [529, 530, 531, 532, 534, 535, 536, 537, 539, 540, 542, 544], "summary": {"covered_lines": 12, "num_statements": 13, "percent_covered": 92.3076923076923, "percent_covered_display": "92", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [541], "excluded_lines": []}, "AlpineBitsFactory.create_res_guests": {"executed_lines": [560, 561, 562], "summary": {"covered_lines": 3, "num_statements": 3, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "AlpineBitsFactory.extract_data": {"executed_lines": [578, 579, 580, 581, 582, 585, 586, 587, 588, 589, 592, 599, 600, 603], "summary": {"covered_lines": 14, "num_statements": 19, "percent_covered": 73.6842105263158, "percent_covered_display": "74", "missing_lines": 5, "excluded_lines": 0}, "missing_lines": [593, 594, 595, 596, 604], "excluded_lines": []}, "create_res_retrieve_response": {"executed_lines": [611], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "create_res_notif_push_message": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [618], "excluded_lines": []}, "_process_single_reservation": {"executed_lines": [627, 631, 648, 649, 652, 653, 657, 662, 663, 664, 665, 666, 670, 673, 676, 680, 684, 688, 689, 691, 692, 693, 699, 700, 708, 710, 717, 718, 722, 724, 725, 727, 733, 734, 735, 746, 747, 748, 759, 762, 764, 765, 766, 767, 774, 775, 777, 778, 779, 781, 785, 787, 791, 793, 795, 797, 804], "summary": {"covered_lines": 57, "num_statements": 66, "percent_covered": 86.36363636363636, "percent_covered_display": "86", "missing_lines": 9, "excluded_lines": 0}, "missing_lines": [658, 659, 660, 661, 668, 694, 695, 696, 723], "excluded_lines": []}, "_create_xml_from_db": {"executed_lines": [824, 828, 831, 832, 838, 839, 843, 845, 846, 851, 853, 869, 870, 874, 878, 879, 884], "summary": {"covered_lines": 17, "num_statements": 30, "percent_covered": 56.666666666666664, "percent_covered_display": "57", "missing_lines": 13, "excluded_lines": 0}, "missing_lines": [829, 854, 858, 862, 863, 864, 865, 866, 868, 880, 881, 882, 886], "excluded_lines": []}, "": {"executed_lines": [1, 2, 3, 4, 5, 7, 8, 9, 19, 28, 31, 32, 35, 36, 39, 42, 45, 48, 53, 56, 60, 61, 63, 66, 70, 71, 73, 74, 76, 80, 81, 82, 85, 86, 87, 89, 92, 93, 95, 96, 117, 118, 147, 148, 150, 151, 155, 156, 160, 161, 225, 226, 230, 231, 235, 236, 304, 305, 307, 308, 316, 317, 325, 326, 337, 338, 346, 347, 355, 356, 368, 369, 371, 372, 376, 377, 381, 382, 416, 417, 421, 422, 426, 427, 449, 450, 453, 454, 456, 457, 463, 464, 470, 471, 497, 498, 511, 512, 514, 515, 546, 547, 564, 565, 607, 614, 621, 815], "summary": {"covered_lines": 101, "num_statements": 101, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"OtaMessageType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "KidsAgeData": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "GuestCountsFactory": {"executed_lines": [107, 108, 128, 129, 130, 131, 132, 134, 136, 137, 140, 142, 143, 144], "summary": {"covered_lines": 14, "num_statements": 18, "percent_covered": 77.77777777777777, "percent_covered_display": "78", "missing_lines": 4, "excluded_lines": 0}, "missing_lines": [111, 112, 115, 138], "excluded_lines": []}, "CustomerFactory": {"executed_lines": [153, 158, 166, 174, 175, 176, 180, 183, 184, 185, 186, 187, 189, 192, 193, 196, 197, 198, 202, 203, 204, 206, 215, 228, 233, 239, 240, 241, 254, 255, 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, 269, 271, 272, 273, 274, 276, 277, 279, 280, 281, 282, 283, 285], "summary": {"covered_lines": 54, "num_statements": 54, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "HotelReservationIdFactory": {"executed_lines": [312, 321, 330, 342, 351, 360], "summary": {"covered_lines": 6, "num_statements": 6, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "CommentFactory": {"executed_lines": [379, 388, 389, 391, 392, 408, 411, 414], "summary": {"covered_lines": 8, "num_statements": 22, "percent_covered": 36.36363636363637, "percent_covered_display": "36", "missing_lines": 14, "excluded_lines": 0}, "missing_lines": [374, 393, 400, 405, 419, 424, 429, 430, 432, 433, 434, 435, 443, 445], "excluded_lines": []}, "ResGuestFactory": {"executed_lines": [459, 466, 478, 481, 486, 489, 492, 495, 503, 506, 507, 508], "summary": {"covered_lines": 12, "num_statements": 12, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "AlpineBitsFactory": {"executed_lines": [529, 530, 531, 532, 534, 535, 536, 537, 539, 540, 542, 544, 560, 561, 562, 578, 579, 580, 581, 582, 585, 586, 587, 588, 589, 592, 599, 600, 603], "summary": {"covered_lines": 29, "num_statements": 35, "percent_covered": 82.85714285714286, "percent_covered_display": "83", "missing_lines": 6, "excluded_lines": 0}, "missing_lines": [541, 593, 594, 595, 596, 604], "excluded_lines": []}, "": {"executed_lines": [1, 2, 3, 4, 5, 7, 8, 9, 19, 28, 31, 32, 35, 36, 39, 42, 45, 48, 53, 56, 60, 61, 63, 66, 70, 71, 73, 74, 76, 80, 81, 82, 85, 86, 87, 89, 92, 93, 95, 96, 117, 118, 147, 148, 150, 151, 155, 156, 160, 161, 225, 226, 230, 231, 235, 236, 304, 305, 307, 308, 316, 317, 325, 326, 337, 338, 346, 347, 355, 356, 368, 369, 371, 372, 376, 377, 381, 382, 416, 417, 421, 422, 426, 427, 449, 450, 453, 454, 456, 457, 463, 464, 470, 471, 497, 498, 511, 512, 514, 515, 546, 547, 564, 565, 607, 611, 614, 621, 627, 631, 648, 649, 652, 653, 657, 662, 663, 664, 665, 666, 670, 673, 676, 680, 684, 688, 689, 691, 692, 693, 699, 700, 708, 710, 717, 718, 722, 724, 725, 727, 733, 734, 735, 746, 747, 748, 759, 762, 764, 765, 766, 767, 774, 775, 777, 778, 779, 781, 785, 787, 791, 793, 795, 797, 804, 815, 824, 828, 831, 832, 838, 839, 843, 845, 846, 851, 853, 869, 870, 874, 878, 879, 884], "summary": {"covered_lines": 176, "num_statements": 199, "percent_covered": 88.44221105527639, "percent_covered_display": "88", "missing_lines": 23, "excluded_lines": 0}, "missing_lines": [618, 658, 659, 660, 661, 668, 694, 695, 696, 723, 829, 854, 858, 862, 863, 864, 865, 866, 868, 880, 881, 882, 886], "excluded_lines": []}}}, "src/alpine_bits_python/alpinebits_server.py": {"executed_lines": [1, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 22, 26, 28, 29, 39, 42, 43, 45, 46, 47, 48, 51, 56, 59, 60, 63, 64, 65, 66, 70, 74, 78, 82, 86, 90, 94, 99, 100, 101, 103, 104, 113, 114, 116, 117, 118, 119, 122, 123, 125, 126, 130, 131, 133, 134, 135, 136, 139, 140, 141, 143, 144, 146, 148, 155, 156, 158, 159, 163, 189, 198, 199, 203, 204, 206, 207, 208, 209, 211, 213, 215, 216, 222, 223, 224, 226, 228, 233, 235, 237, 239, 240, 243, 244, 249, 250, 252, 253, 255, 258, 261, 263, 266, 267, 268, 269, 270, 271, 272, 273, 276, 277, 278, 284, 286, 287, 288, 290, 298, 299, 301, 302, 303, 307, 309, 310, 319, 324, 330, 332, 333, 335, 342, 344, 345, 348, 349, 352, 353, 355, 358, 362, 368, 369, 371, 376, 377, 378, 383, 385, 391, 393, 395, 402, 406, 408, 412, 415, 417, 420, 432, 434, 435, 436, 441, 447, 448, 450, 451, 452, 453, 455, 465, 466, 468, 474, 479, 481, 483, 484, 486, 489, 495, 503, 505, 508, 509, 515, 520, 521, 522, 524, 525, 533, 535, 536, 540, 544, 545, 552, 556, 559, 560, 564, 567, 568, 570, 571, 572, 573, 575, 585, 589, 590, 592, 594, 599, 602, 603, 607, 614, 619, 620, 623, 624, 629, 631, 633, 636, 637, 639, 640, 641, 642, 644, 669, 670, 677, 678, 679, 680, 681, 683, 685, 686, 687, 689, 693, 713, 714, 721, 723, 726, 727, 734, 740, 743, 750, 753, 767, 768, 775, 792, 801], "summary": {"covered_lines": 254, "num_statements": 318, "percent_covered": 79.87421383647799, "percent_covered_display": "80", "missing_lines": 64, "excluded_lines": 0}, "missing_lines": [108, 109, 110, 111, 149, 186, 187, 200, 246, 259, 292, 320, 325, 336, 337, 433, 442, 469, 475, 487, 490, 498, 595, 611, 615, 654, 658, 661, 662, 666, 691, 715, 716, 735, 744, 755, 756, 760, 782, 784, 786, 787, 794, 795, 796, 797, 798, 799, 814, 815, 816, 818, 819, 820, 822, 823, 824, 825, 827, 828, 829, 830, 831, 833], "excluded_lines": [], "functions": {"dump_json_for_xml": {"executed_lines": [56], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "AlpineBitsActionName.__init__": {"executed_lines": [100, 101], "summary": {"covered_lines": 2, "num_statements": 2, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "AlpineBitsActionName.get_by_capability_name": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 4, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 4, "excluded_lines": 0}, "missing_lines": [108, 109, 110, 111], "excluded_lines": []}, "AlpineBitsActionName.get_by_request_name": {"executed_lines": [116, 117, 118, 119], "summary": {"covered_lines": 4, "num_statements": 4, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "AlpineBitsClientInfo.__init__": {"executed_lines": [134, 135, 136], "summary": {"covered_lines": 3, "num_statements": 3, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "AlpineBitsResponse.__post_init__": {"executed_lines": [148], "summary": {"covered_lines": 1, "num_statements": 2, "percent_covered": 50.0, "percent_covered_display": "50", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [149], "excluded_lines": []}, "AlpineBitsAction.handle": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [186, 187], "excluded_lines": []}, "AlpineBitsAction.check_version_supported": {"executed_lines": [198, 199], "summary": {"covered_lines": 2, "num_statements": 3, "percent_covered": 66.66666666666667, "percent_covered_display": "67", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [200], "excluded_lines": []}, "ServerCapabilities.__init__": {"executed_lines": [207, 208, 209], "summary": {"covered_lines": 3, "num_statements": 3, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ServerCapabilities._discover_actions": {"executed_lines": [213, 215, 216, 222, 223, 224, 226], "summary": {"covered_lines": 7, "num_statements": 7, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ServerCapabilities._is_action_implemented": {"executed_lines": [233], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ServerCapabilities.create_capabilities_dict": {"executed_lines": [237, 239, 240, 243, 244, 249, 250, 252, 253, 255, 258, 261, 263, 266, 267, 268, 269, 270, 271, 272, 273, 276, 277, 278], "summary": {"covered_lines": 24, "num_statements": 26, "percent_covered": 92.3076923076923, "percent_covered_display": "92", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [246, 259], "excluded_lines": []}, "ServerCapabilities.get_capabilities_dict": {"executed_lines": [286, 287, 288], "summary": {"covered_lines": 3, "num_statements": 3, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ServerCapabilities.get_supported_actions": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [292], "excluded_lines": []}, "PingAction.__init__": {"executed_lines": [302, 303, 307], "summary": {"covered_lines": 3, "num_statements": 3, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "PingAction.handle": {"executed_lines": [319, 324, 330, 332, 333, 335, 342, 344, 345, 348, 349, 352, 353, 355, 358, 362, 368, 369, 371, 376, 377, 378, 383, 385, 391, 393, 395, 402, 406, 408, 412], "summary": {"covered_lines": 31, "num_statements": 35, "percent_covered": 88.57142857142857, "percent_covered_display": "89", "missing_lines": 4, "excluded_lines": 0}, "missing_lines": [320, 325, 336, 337], "excluded_lines": []}, "strip_control_chars": {"executed_lines": [417], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "validate_hotel_authentication": {"executed_lines": [432, 434, 435, 436, 441], "summary": {"covered_lines": 5, "num_statements": 7, "percent_covered": 71.42857142857143, "percent_covered_display": "71", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [433, 442], "excluded_lines": []}, "ReadAction.__init__": {"executed_lines": [451, 452, 453], "summary": {"covered_lines": 3, "num_statements": 3, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ReadAction.handle": {"executed_lines": [465, 466, 468, 474, 479, 481, 483, 484, 486, 489, 495, 503, 505, 508, 509, 515, 520, 521, 522, 524, 525, 533, 535, 536, 540, 544, 545, 552, 556, 559, 560, 564], "summary": {"covered_lines": 32, "num_statements": 37, "percent_covered": 86.48648648648648, "percent_covered_display": "86", "missing_lines": 5, "excluded_lines": 0}, "missing_lines": [469, 475, 487, 490, 498], "excluded_lines": []}, "NotifReportReadAction.__init__": {"executed_lines": [571, 572, 573], "summary": {"covered_lines": 3, "num_statements": 3, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "NotifReportReadAction.handle": {"executed_lines": [585, 589, 590, 592, 594, 599, 602, 603, 607, 614, 619, 620, 623, 624, 629, 631, 633], "summary": {"covered_lines": 17, "num_statements": 20, "percent_covered": 85.0, "percent_covered_display": "85", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [595, 611, 615], "excluded_lines": []}, "PushAction.__init__": {"executed_lines": [640, 641, 642], "summary": {"covered_lines": 3, "num_statements": 3, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "PushAction.handle": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 5, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 5, "excluded_lines": 0}, "missing_lines": [654, 658, 661, 662, 666], "excluded_lines": []}, "AlpineBitsServer.__init__": {"executed_lines": [678, 679, 680, 681], "summary": {"covered_lines": 4, "num_statements": 4, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "AlpineBitsServer._initialize_action_instances": {"executed_lines": [685, 686, 687], "summary": {"covered_lines": 3, "num_statements": 3, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "AlpineBitsServer.get_capabilities": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [691], "excluded_lines": []}, "AlpineBitsServer.handle_request": {"executed_lines": [713, 714, 721, 723, 726, 727, 734, 740, 743, 750, 753, 767, 768, 775], "summary": {"covered_lines": 14, "num_statements": 25, "percent_covered": 56.0, "percent_covered_display": "56", "missing_lines": 11, "excluded_lines": 0}, "missing_lines": [715, 716, 735, 744, 755, 756, 760, 782, 784, 786, 787], "excluded_lines": []}, "AlpineBitsServer.get_supported_request_names": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 6, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 6, "excluded_lines": 0}, "missing_lines": [794, 795, 796, 797, 798, 799], "excluded_lines": []}, "AlpineBitsServer.is_action_supported": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 16, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 16, "excluded_lines": 0}, "missing_lines": [814, 815, 816, 818, 819, 820, 822, 823, 824, 825, 827, 828, 829, 830, 831, 833], "excluded_lines": []}, "": {"executed_lines": [1, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 22, 26, 28, 29, 39, 42, 43, 45, 46, 47, 48, 51, 59, 60, 63, 64, 65, 66, 70, 74, 78, 82, 86, 90, 94, 99, 103, 104, 113, 114, 122, 123, 125, 126, 130, 131, 133, 139, 140, 141, 143, 144, 146, 155, 156, 158, 159, 163, 189, 203, 204, 206, 211, 228, 235, 284, 290, 298, 299, 301, 309, 310, 415, 420, 447, 448, 450, 455, 567, 568, 570, 575, 636, 637, 639, 644, 669, 670, 677, 683, 689, 693, 792, 801], "summary": {"covered_lines": 84, "num_statements": 84, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"HttpStatusCode": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "AlpineBitsActionName": {"executed_lines": [100, 101, 116, 117, 118, 119], "summary": {"covered_lines": 6, "num_statements": 10, "percent_covered": 60.0, "percent_covered_display": "60", "missing_lines": 4, "excluded_lines": 0}, "missing_lines": [108, 109, 110, 111], "excluded_lines": []}, "Version": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "AlpineBitsClientInfo": {"executed_lines": [134, 135, 136], "summary": {"covered_lines": 3, "num_statements": 3, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "AlpineBitsResponse": {"executed_lines": [148], "summary": {"covered_lines": 1, "num_statements": 2, "percent_covered": 50.0, "percent_covered_display": "50", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [149], "excluded_lines": []}, "AlpineBitsAction": {"executed_lines": [198, 199], "summary": {"covered_lines": 2, "num_statements": 5, "percent_covered": 40.0, "percent_covered_display": "40", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [186, 187, 200], "excluded_lines": []}, "ServerCapabilities": {"executed_lines": [207, 208, 209, 213, 215, 216, 222, 223, 224, 226, 233, 237, 239, 240, 243, 244, 249, 250, 252, 253, 255, 258, 261, 263, 266, 267, 268, 269, 270, 271, 272, 273, 276, 277, 278, 286, 287, 288], "summary": {"covered_lines": 38, "num_statements": 41, "percent_covered": 92.6829268292683, "percent_covered_display": "93", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [246, 259, 292], "excluded_lines": []}, "PingAction": {"executed_lines": [302, 303, 307, 319, 324, 330, 332, 333, 335, 342, 344, 345, 348, 349, 352, 353, 355, 358, 362, 368, 369, 371, 376, 377, 378, 383, 385, 391, 393, 395, 402, 406, 408, 412], "summary": {"covered_lines": 34, "num_statements": 38, "percent_covered": 89.47368421052632, "percent_covered_display": "89", "missing_lines": 4, "excluded_lines": 0}, "missing_lines": [320, 325, 336, 337], "excluded_lines": []}, "ReadAction": {"executed_lines": [451, 452, 453, 465, 466, 468, 474, 479, 481, 483, 484, 486, 489, 495, 503, 505, 508, 509, 515, 520, 521, 522, 524, 525, 533, 535, 536, 540, 544, 545, 552, 556, 559, 560, 564], "summary": {"covered_lines": 35, "num_statements": 40, "percent_covered": 87.5, "percent_covered_display": "88", "missing_lines": 5, "excluded_lines": 0}, "missing_lines": [469, 475, 487, 490, 498], "excluded_lines": []}, "NotifReportReadAction": {"executed_lines": [571, 572, 573, 585, 589, 590, 592, 594, 599, 602, 603, 607, 614, 619, 620, 623, 624, 629, 631, 633], "summary": {"covered_lines": 20, "num_statements": 23, "percent_covered": 86.95652173913044, "percent_covered_display": "87", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [595, 611, 615], "excluded_lines": []}, "PushAction": {"executed_lines": [640, 641, 642], "summary": {"covered_lines": 3, "num_statements": 8, "percent_covered": 37.5, "percent_covered_display": "38", "missing_lines": 5, "excluded_lines": 0}, "missing_lines": [654, 658, 661, 662, 666], "excluded_lines": []}, "AlpineBitsServer": {"executed_lines": [678, 679, 680, 681, 685, 686, 687, 713, 714, 721, 723, 726, 727, 734, 740, 743, 750, 753, 767, 768, 775], "summary": {"covered_lines": 21, "num_statements": 55, "percent_covered": 38.18181818181818, "percent_covered_display": "38", "missing_lines": 34, "excluded_lines": 0}, "missing_lines": [691, 715, 716, 735, 744, 755, 756, 760, 782, 784, 786, 787, 794, 795, 796, 797, 798, 799, 814, 815, 816, 818, 819, 820, 822, 823, 824, 825, 827, 828, 829, 830, 831, 833], "excluded_lines": []}, "": {"executed_lines": [1, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 22, 26, 28, 29, 39, 42, 43, 45, 46, 47, 48, 51, 56, 59, 60, 63, 64, 65, 66, 70, 74, 78, 82, 86, 90, 94, 99, 103, 104, 113, 114, 122, 123, 125, 126, 130, 131, 133, 139, 140, 141, 143, 144, 146, 155, 156, 158, 159, 163, 189, 203, 204, 206, 211, 228, 235, 284, 290, 298, 299, 301, 309, 310, 415, 417, 420, 432, 434, 435, 436, 441, 447, 448, 450, 455, 567, 568, 570, 575, 636, 637, 639, 644, 669, 670, 677, 683, 689, 693, 792, 801], "summary": {"covered_lines": 91, "num_statements": 93, "percent_covered": 97.84946236559139, "percent_covered_display": "98", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [433, 442], "excluded_lines": []}}}, "src/alpine_bits_python/api.py": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 389, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 389, "excluded_lines": 0}, "missing_lines": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 20, 22, 28, 29, 30, 31, 32, 33, 34, 44, 47, 51, 52, 53, 54, 56, 57, 59, 61, 63, 64, 65, 67, 69, 70, 71, 74, 79, 84, 85, 86, 89, 91, 92, 93, 96, 97, 102, 104, 112, 119, 120, 126, 130, 131, 132, 133, 134, 137, 138, 140, 141, 142, 169, 172, 173, 174, 175, 176, 179, 180, 182, 183, 184, 186, 187, 188, 189, 190, 193, 194, 195, 197, 199, 202, 207, 208, 209, 210, 213, 214, 215, 217, 220, 223, 224, 225, 226, 229, 237, 240, 241, 244, 258, 259, 260, 262, 275, 276, 277, 279, 289, 293, 295, 296, 297, 300, 302, 306, 308, 310, 313, 321, 322, 323, 324, 325, 328, 329, 332, 333, 334, 335, 336, 337, 339, 343, 344, 345, 346, 347, 348, 349, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 364, 369, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 388, 392, 397, 415, 416, 421, 428, 435, 436, 437, 438, 441, 442, 443, 445, 466, 467, 469, 470, 471, 472, 474, 476, 477, 479, 480, 481, 484, 486, 490, 492, 502, 510, 511, 516, 517, 519, 520, 524, 525, 526, 527, 532, 536, 539, 540, 541, 548, 549, 550, 551, 553, 555, 556, 557, 560, 561, 562, 569, 570, 571, 572, 573, 576, 577, 578, 590, 592, 593, 596, 598, 599, 604, 605, 608, 609, 610, 611, 612, 618, 619, 620, 622, 625, 626, 631, 632, 633, 634, 637, 638, 640, 641, 642, 645, 647, 654, 659, 663, 664, 665, 666, 667, 671, 675, 676, 681, 682, 683, 684, 685, 686, 688, 689, 694, 695, 697, 698, 699, 702, 703, 704, 707, 708, 709, 710, 712, 713, 714, 715, 716, 718, 720, 722, 724, 726, 729, 730, 731, 750, 752, 755, 757, 758, 762, 765, 766, 767, 770, 771, 773, 774, 777, 779, 780, 783, 786, 789, 790, 791, 795, 798, 800, 802, 804, 806, 811, 819, 822, 828, 830, 831, 833, 837, 839, 840, 841, 842, 845, 847, 848, 849, 851, 852, 858, 862, 868, 869, 870, 871, 872, 876, 878, 880, 885, 888, 889, 890, 894, 895, 898, 911, 914, 915, 917, 919, 921, 922, 924, 925, 927, 945, 948, 949, 951], "excluded_lines": [], "functions": {"EventDispatcher.__init__": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [53, 54], "excluded_lines": []}, "EventDispatcher.register": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [57], "excluded_lines": []}, "EventDispatcher.register_hotel_listener": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [61], "excluded_lines": []}, "EventDispatcher.dispatch": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [64, 65], "excluded_lines": []}, "EventDispatcher.dispatch_for_hotel": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [69, 70, 71], "excluded_lines": []}, "push_listener": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 25, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 25, "excluded_lines": 0}, "missing_lines": [84, 85, 86, 89, 91, 92, 93, 96, 97, 102, 104, 112, 119, 120, 126, 130, 131, 132, 133, 134, 137, 138, 140, 141, 142], "excluded_lines": []}, "lifespan": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 30, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 30, "excluded_lines": 0}, "missing_lines": [172, 173, 174, 175, 176, 179, 180, 182, 183, 184, 186, 187, 188, 189, 190, 193, 194, 195, 197, 199, 202, 207, 208, 209, 210, 213, 214, 215, 217, 220], "excluded_lines": []}, "get_async_session": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [224, 225, 226], "excluded_lines": []}, "root": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [262], "excluded_lines": []}, "health_check": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [279], "excluded_lines": []}, "create_db_reservation_from_data": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 6, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 6, "excluded_lines": 0}, "missing_lines": [293, 295, 296, 297, 300, 302], "excluded_lines": []}, "process_wix_form_submission": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 72, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 72, "excluded_lines": 0}, "missing_lines": [308, 310, 313, 321, 322, 323, 324, 325, 328, 329, 332, 333, 334, 335, 336, 337, 339, 343, 344, 345, 346, 347, 348, 349, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 364, 369, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 388, 392, 397, 415, 416, 421, 428, 435, 436, 437, 438, 441, 442, 443, 445, 466, 467, 469, 470, 471, 472, 474, 490, 492], "excluded_lines": []}, "process_wix_form_submission.push_event": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 7, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 7, "excluded_lines": 0}, "missing_lines": [476, 477, 479, 480, 481, 484, 486], "excluded_lines": []}, "validate_basic_auth": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 12, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 12, "excluded_lines": 0}, "missing_lines": [510, 511, 516, 517, 519, 520, 524, 525, 526, 527, 532, 536], "excluded_lines": []}, "handle_wix_form": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 8, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 8, "excluded_lines": 0}, "missing_lines": [548, 549, 550, 551, 553, 555, 556, 557], "excluded_lines": []}, "handle_wix_form_test": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 5, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 5, "excluded_lines": 0}, "missing_lines": [569, 570, 571, 572, 573], "excluded_lines": []}, "handle_xml_upload": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 37, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 37, "excluded_lines": 0}, "missing_lines": [590, 592, 593, 596, 598, 599, 604, 605, 608, 609, 610, 611, 612, 618, 619, 620, 622, 625, 626, 631, 632, 633, 634, 637, 638, 640, 641, 642, 645, 647, 654, 659, 663, 664, 665, 666, 667], "excluded_lines": []}, "parse_multipart_data": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 32, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 32, "excluded_lines": 0}, "missing_lines": [675, 676, 681, 682, 683, 684, 685, 686, 688, 689, 694, 695, 697, 698, 699, 702, 703, 704, 707, 708, 709, 710, 712, 713, 714, 715, 716, 718, 720, 722, 724, 726], "excluded_lines": []}, "alpinebits_server_handshake": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 39, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 39, "excluded_lines": 0}, "missing_lines": [750, 752, 755, 757, 758, 762, 765, 766, 767, 770, 771, 773, 774, 777, 779, 780, 783, 786, 789, 790, 791, 795, 798, 800, 802, 804, 806, 811, 819, 822, 828, 830, 831, 833, 837, 839, 840, 841, 842], "excluded_lines": []}, "validate_alpinebits_body": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 16, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 16, "excluded_lines": 0}, "missing_lines": [847, 848, 849, 851, 852, 858, 862, 868, 869, 870, 871, 872, 876, 878, 880, 885], "excluded_lines": []}, "get_api_stats": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [894, 895, 898], "excluded_lines": []}, "landing_page": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 8, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 8, "excluded_lines": 0}, "missing_lines": [917, 919, 921, 922, 924, 925, 927, 945], "excluded_lines": []}, "": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 75, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 75, "excluded_lines": 0}, "missing_lines": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 20, 22, 28, 29, 30, 31, 32, 33, 34, 44, 47, 51, 52, 56, 59, 63, 67, 74, 79, 169, 223, 229, 237, 240, 241, 244, 258, 259, 260, 275, 276, 277, 289, 306, 502, 539, 540, 541, 560, 561, 562, 576, 577, 578, 671, 729, 730, 731, 845, 888, 889, 890, 911, 914, 915, 948, 949, 951], "excluded_lines": []}}, "classes": {"EventDispatcher": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 9, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 9, "excluded_lines": 0}, "missing_lines": [53, 54, 57, 61, 64, 65, 69, 70, 71], "excluded_lines": []}, "": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 380, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 380, "excluded_lines": 0}, "missing_lines": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 20, 22, 28, 29, 30, 31, 32, 33, 34, 44, 47, 51, 52, 56, 59, 63, 67, 74, 79, 84, 85, 86, 89, 91, 92, 93, 96, 97, 102, 104, 112, 119, 120, 126, 130, 131, 132, 133, 134, 137, 138, 140, 141, 142, 169, 172, 173, 174, 175, 176, 179, 180, 182, 183, 184, 186, 187, 188, 189, 190, 193, 194, 195, 197, 199, 202, 207, 208, 209, 210, 213, 214, 215, 217, 220, 223, 224, 225, 226, 229, 237, 240, 241, 244, 258, 259, 260, 262, 275, 276, 277, 279, 289, 293, 295, 296, 297, 300, 302, 306, 308, 310, 313, 321, 322, 323, 324, 325, 328, 329, 332, 333, 334, 335, 336, 337, 339, 343, 344, 345, 346, 347, 348, 349, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 364, 369, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 388, 392, 397, 415, 416, 421, 428, 435, 436, 437, 438, 441, 442, 443, 445, 466, 467, 469, 470, 471, 472, 474, 476, 477, 479, 480, 481, 484, 486, 490, 492, 502, 510, 511, 516, 517, 519, 520, 524, 525, 526, 527, 532, 536, 539, 540, 541, 548, 549, 550, 551, 553, 555, 556, 557, 560, 561, 562, 569, 570, 571, 572, 573, 576, 577, 578, 590, 592, 593, 596, 598, 599, 604, 605, 608, 609, 610, 611, 612, 618, 619, 620, 622, 625, 626, 631, 632, 633, 634, 637, 638, 640, 641, 642, 645, 647, 654, 659, 663, 664, 665, 666, 667, 671, 675, 676, 681, 682, 683, 684, 685, 686, 688, 689, 694, 695, 697, 698, 699, 702, 703, 704, 707, 708, 709, 710, 712, 713, 714, 715, 716, 718, 720, 722, 724, 726, 729, 730, 731, 750, 752, 755, 757, 758, 762, 765, 766, 767, 770, 771, 773, 774, 777, 779, 780, 783, 786, 789, 790, 791, 795, 798, 800, 802, 804, 806, 811, 819, 822, 828, 830, 831, 833, 837, 839, 840, 841, 842, 845, 847, 848, 849, 851, 852, 858, 862, 868, 869, 870, 871, 872, 876, 878, 880, 885, 888, 889, 890, 894, 895, 898, 911, 914, 915, 917, 919, 921, 922, 924, 925, 927, 945, 948, 949, 951], "excluded_lines": []}}}, "src/alpine_bits_python/auth.py": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 52, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 52, "excluded_lines": 0}, "missing_lines": [1, 2, 3, 4, 6, 7, 8, 11, 12, 14, 17, 20, 27, 28, 29, 30, 33, 35, 38, 40, 43, 50, 53, 54, 55, 56, 58, 59, 66, 71, 72, 74, 76, 79, 84, 85, 86, 87, 90, 93, 94, 96, 98, 99, 100, 101, 103, 105, 107, 109, 110, 114], "excluded_lines": [], "functions": {"generate_unique_id": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [35], "excluded_lines": []}, "generate_api_key": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [40], "excluded_lines": []}, "validate_api_key": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 7, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 7, "excluded_lines": 0}, "missing_lines": [50, 53, 54, 55, 56, 58, 59], "excluded_lines": []}, "validate_wix_signature": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 9, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 9, "excluded_lines": 0}, "missing_lines": [71, 72, 74, 76, 79, 84, 85, 86, 87], "excluded_lines": []}, "APIKeyAuth.__init__": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [94], "excluded_lines": []}, "APIKeyAuth.authenticate": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 4, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 4, "excluded_lines": 0}, "missing_lines": [98, 99, 100, 101], "excluded_lines": []}, "APIKeyAuth.add_key": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [105], "excluded_lines": []}, "APIKeyAuth.remove_key": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [109, 110], "excluded_lines": []}, "": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 26, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 26, "excluded_lines": 0}, "missing_lines": [1, 2, 3, 4, 6, 7, 8, 11, 12, 14, 17, 20, 27, 28, 29, 30, 33, 38, 43, 66, 90, 93, 96, 103, 107, 114], "excluded_lines": []}}, "classes": {"APIKeyAuth": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 8, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 8, "excluded_lines": 0}, "missing_lines": [94, 98, 99, 100, 101, 105, 109, 110], "excluded_lines": []}, "": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 44, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 44, "excluded_lines": 0}, "missing_lines": [1, 2, 3, 4, 6, 7, 8, 11, 12, 14, 17, 20, 27, 28, 29, 30, 33, 35, 38, 40, 43, 50, 53, 54, 55, 56, 58, 59, 66, 71, 72, 74, 76, 79, 84, 85, 86, 87, 90, 93, 96, 103, 107, 114], "excluded_lines": []}}}, "src/alpine_bits_python/config_loader.py": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 55, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 55, "excluded_lines": 0}, "missing_lines": [1, 2, 4, 5, 6, 16, 39, 42, 51, 53, 54, 55, 58, 68, 83, 85, 95, 98, 99, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 117, 118, 119, 120, 121, 122, 123, 124, 125, 127, 128, 130, 131, 132, 134, 135, 136, 138, 139, 140, 142, 143, 144, 148, 149], "excluded_lines": [], "functions": {"ensure_string": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [53, 54, 55], "excluded_lines": []}, "Config.__init__": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 11, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 11, "excluded_lines": 0}, "missing_lines": [105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115], "excluded_lines": []}, "Config._load_config": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 8, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 8, "excluded_lines": 0}, "missing_lines": [118, 119, 120, 121, 122, 123, 124, 125], "excluded_lines": []}, "Config.get": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [128], "excluded_lines": []}, "Config.db_url": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [132], "excluded_lines": []}, "Config.hotel_id": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [136], "excluded_lines": []}, "Config.hotel_name": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [140], "excluded_lines": []}, "Config.users": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [144], "excluded_lines": []}, "load_config": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [149], "excluded_lines": []}, "": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 27, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 27, "excluded_lines": 0}, "missing_lines": [1, 2, 4, 5, 6, 16, 39, 42, 51, 58, 68, 83, 85, 95, 98, 99, 117, 127, 130, 131, 134, 135, 138, 139, 142, 143, 148], "excluded_lines": []}}, "classes": {"Config": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 24, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 24, "excluded_lines": 0}, "missing_lines": [105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 118, 119, 120, 121, 122, 123, 124, 125, 128, 132, 136, 140, 144], "excluded_lines": []}, "": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 31, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 31, "excluded_lines": 0}, "missing_lines": [1, 2, 4, 5, 6, 16, 39, 42, 51, 53, 54, 55, 58, 68, 83, 85, 95, 98, 99, 117, 127, 130, 131, 134, 135, 138, 139, 142, 143, 148, 149], "excluded_lines": []}}}, "src/alpine_bits_python/const.py": {"executed_lines": [1, 3, 8, 10, 11, 14, 17, 18, 19, 20, 21, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34], "summary": {"covered_lines": 21, "num_statements": 21, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": [], "functions": {"": {"executed_lines": [1, 3, 8, 10, 11, 14, 17, 18, 19, 20, 21, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34], "summary": {"covered_lines": 21, "num_statements": 21, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"": {"executed_lines": [1, 3, 8, 10, 11, 14, 17, 18, 19, 20, 21, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34], "summary": {"covered_lines": 21, "num_statements": 21, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "src/alpine_bits_python/db.py": {"executed_lines": [1, 3, 4, 6, 10, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, 72, 73, 74, 75, 76, 79], "summary": {"covered_lines": 55, "num_statements": 63, "percent_covered": 87.3015873015873, "percent_covered_display": "87", "missing_lines": 8, "excluded_lines": 0}, "missing_lines": [11, 12, 13, 14, 15, 16, 17, 18], "excluded_lines": [], "functions": {"get_database_url": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 8, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 8, "excluded_lines": 0}, "missing_lines": [11, 12, 13, 14, 15, 16, 17, 18], "excluded_lines": []}, "": {"executed_lines": [1, 3, 4, 6, 10, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, 72, 73, 74, 75, 76, 79], "summary": {"covered_lines": 55, "num_statements": 55, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"Customer": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "Reservation": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "AckedRequest": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [1, 3, 4, 6, 10, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, 72, 73, 74, 75, 76, 79], "summary": {"covered_lines": 55, "num_statements": 63, "percent_covered": 87.3015873015873, "percent_covered_display": "87", "missing_lines": 8, "excluded_lines": 0}, "missing_lines": [11, 12, 13, 14, 15, 16, 17, 18], "excluded_lines": []}}}, "src/alpine_bits_python/generated/__init__.py": {"executed_lines": [1, 82], "summary": {"covered_lines": 2, "num_statements": 2, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": [], "functions": {"": {"executed_lines": [1, 82], "summary": {"covered_lines": 2, "num_statements": 2, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"": {"executed_lines": [1, 82], "summary": {"covered_lines": 2, "num_statements": 2, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "src/alpine_bits_python/generated/alpinebits.py": {"executed_lines": [1, 2, 3, 5, 6, 7, 9, 12, 13, 14, 17, 18, 21, 22, 23, 24, 25, 28, 29, 30, 31, 34, 35, 38, 39, 40, 41, 42, 43, 46, 47, 48, 51, 52, 55, 56, 59, 60, 63, 64, 65, 68, 69, 72, 73, 76, 77, 78, 79, 80, 83, 84, 85, 86, 87, 88, 89, 92, 93, 94, 95, 98, 99, 100, 101, 102, 105, 106, 107, 108, 111, 112, 115, 116, 117, 118, 119, 120, 123, 124, 125, 128, 129, 130, 131, 132, 135, 136, 137, 138, 141, 142, 143, 144, 146, 147, 154, 161, 169, 170, 171, 179, 180, 181, 190, 201, 202, 203, 204, 206, 207, 214, 221, 229, 230, 231, 239, 240, 241, 248, 257, 265, 266, 267, 275, 284, 285, 286, 297, 298, 299, 308, 318, 319, 320, 329, 340, 341, 342, 343, 345, 346, 354, 361, 370, 371, 372, 373, 375, 376, 383, 390, 398, 399, 400, 408, 409, 410, 419, 428, 438, 439, 440, 450, 451, 452, 455, 456, 459, 460, 461, 464, 465, 468, 469, 472, 473, 474, 475, 476, 479, 480, 483, 484, 487, 488, 491, 492, 493, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 508, 509, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 524, 525, 526, 527, 528, 529, 532, 533, 536, 537, 538, 541, 542, 543, 546, 547, 548, 551, 552, 553, 554, 555, 556, 557, 558, 561, 562, 563, 566, 567, 570, 571, 574, 575, 578, 579, 582, 583, 584, 587, 588, 590, 591, 592, 593, 594, 595, 596, 597, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 612, 613, 616, 617, 620, 621, 622, 625, 626, 627, 630, 631, 634, 635, 636, 637, 638, 639, 640, 643, 644, 647, 648, 649, 650, 651, 654, 655, 656, 657, 659, 660, 667, 674, 682, 683, 684, 692, 693, 694, 703, 712, 721, 730, 739, 748, 757, 766, 775, 776, 777, 786, 795, 804, 813, 822, 823, 824, 832, 833, 834, 842, 852, 853, 854, 862, 863, 864, 875, 876, 877, 886, 895, 904, 912, 913, 914, 924, 925, 926, 936, 945, 955, 956, 957, 964, 971, 980, 981, 982, 993, 994, 995, 1002, 1011, 1019, 1020, 1021, 1029, 1038, 1047, 1056, 1064, 1073, 1074, 1075, 1082, 1089, 1098, 1099, 1100, 1111, 1112, 1113, 1120, 1129, 1137, 1138, 1139, 1147, 1156, 1165, 1174, 1183, 1184, 1185, 1192, 1199, 1208, 1209, 1210, 1217, 1224, 1231, 1239, 1240, 1241, 1251, 1252, 1253, 1262, 1270, 1277, 1285, 1294, 1295, 1296, 1306, 1307, 1308, 1317, 1318, 1319, 1327, 1328, 1329, 1339, 1340, 1341, 1348, 1357, 1366, 1375, 1383, 1391, 1399, 1409, 1410, 1411, 1419, 1427, 1436, 1444, 1452, 1453, 1454, 1465, 1466, 1467, 1476, 1477, 1478, 1488, 1489, 1490, 1499, 1508, 1518, 1519, 1520, 1528, 1529, 1530, 1541, 1542, 1543, 1550, 1557, 1566, 1567, 1568, 1579, 1580, 1581, 1588, 1597, 1606, 1607, 1608, 1616, 1626, 1627, 1628, 1635, 1642, 1651, 1652, 1653, 1664, 1665, 1666, 1675, 1684, 1693, 1702, 1711, 1720, 1730, 1731, 1732, 1740, 1741, 1742, 1750, 1751, 1752, 1763, 1764, 1765, 1772, 1779, 1788, 1789, 1790, 1798, 1799, 1800, 1807, 1816, 1825, 1834, 1835, 1836, 1847, 1848, 1849, 1856, 1863, 1872, 1873, 1874, 1882, 1883, 1884, 1891, 1899, 1908, 1916, 1925, 1934, 1935, 1936, 1947, 1948, 1949, 1956, 1963, 1972, 1973, 1974, 1982, 1983, 1984, 1991, 2000, 2009, 2017, 2024, 2033, 2041, 2042, 2043, 2054, 2055, 2056, 2063, 2070, 2079, 2080, 2081, 2089, 2090, 2091, 2098, 2107, 2117, 2118, 2119, 2130, 2131, 2132, 2141, 2150, 2160, 2161, 2162, 2171, 2178, 2186, 2187, 2188, 2197, 2198, 2199, 2208, 2209, 2210, 2219, 2220, 2221, 2229, 2238, 2239, 2240, 2250, 2251, 2252, 2260, 2267, 2276, 2277, 2278, 2287, 2288, 2289, 2301, 2302, 2303, 2310, 2318, 2327, 2328, 2329, 2337, 2338, 2339, 2350, 2351, 2352, 2361, 2369, 2377, 2386, 2387, 2388, 2396, 2397, 2398, 2407, 2416, 2425, 2434, 2442, 2450, 2451, 2452, 2463, 2464, 2465, 2474, 2483, 2492, 2501, 2510, 2519, 2520, 2521, 2530, 2531, 2532, 2541, 2542, 2543, 2554, 2555, 2556, 2564, 2573, 2574, 2575, 2586, 2587, 2588, 2595, 2604, 2605, 2606, 2617, 2618, 2619, 2625, 2635, 2636, 2637, 2638, 2640, 2641, 2648, 2655, 2662, 2669, 2677, 2678, 2679, 2688, 2689, 2690, 2697, 2705, 2712, 2721, 2722, 2723, 2732, 2733, 2734, 2742, 2751, 2758, 2768, 2769, 2770, 2771, 2773, 2774, 2781, 2788, 2795, 2804, 2811, 2819, 2820, 2821, 2830, 2831, 2832, 2839, 2847, 2854, 2863, 2864, 2865, 2874, 2875, 2876, 2884, 2893, 2900, 2909, 2910, 2911, 2919, 2920, 2921, 2930, 2939, 2948, 2957, 2966, 2975, 2984, 2993, 3002, 3003, 3004, 3013, 3022, 3031, 3040, 3049, 3050, 3051, 3059, 3060, 3061, 3069, 3079, 3080, 3081, 3089, 3090, 3091, 3102, 3103, 3104, 3113, 3122, 3131, 3139, 3140, 3141, 3151, 3152, 3153, 3163, 3172, 3182, 3183, 3184, 3191, 3198, 3207, 3208, 3209, 3220, 3221, 3222, 3229, 3238, 3246, 3247, 3248, 3256, 3265, 3274, 3283, 3291, 3300, 3301, 3302, 3309, 3316, 3325, 3326, 3327, 3338, 3339, 3340, 3347, 3356, 3364, 3365, 3366, 3374, 3383, 3392, 3401, 3410, 3411, 3412, 3419, 3426, 3435, 3436, 3437, 3444, 3451, 3458, 3466, 3467, 3468, 3478, 3479, 3480, 3489, 3497, 3504, 3512, 3521, 3522, 3523, 3533, 3534, 3535, 3544, 3545, 3546, 3554, 3555, 3556, 3566, 3567, 3568, 3575, 3584, 3593, 3602, 3610, 3618, 3626, 3636, 3637, 3638, 3646, 3654, 3663, 3671, 3679, 3680, 3681, 3692, 3693, 3694, 3703, 3704, 3705, 3715, 3716, 3717, 3726, 3735, 3745, 3746, 3747, 3755, 3756, 3757, 3768, 3769, 3770, 3777, 3784, 3793, 3794, 3795, 3806, 3807, 3808, 3815, 3824, 3833, 3834, 3835, 3843, 3853, 3854, 3855, 3862, 3869, 3878, 3879, 3880, 3891, 3892, 3893, 3902, 3911, 3920, 3929, 3938, 3947, 3957, 3958, 3959, 3967, 3968, 3969, 3977, 3978, 3979, 3990, 3991, 3992, 3999, 4006, 4015, 4016, 4017, 4025, 4026, 4027, 4034, 4043, 4052, 4061, 4062, 4063, 4074, 4075, 4076, 4083, 4090, 4099, 4100, 4101, 4109, 4110, 4111, 4118, 4126, 4135, 4143, 4152, 4161, 4162, 4163, 4174, 4175, 4176, 4183, 4190, 4199, 4200, 4201, 4209, 4210, 4211, 4218, 4227, 4236, 4244, 4251, 4260, 4268, 4269, 4270, 4281, 4282, 4283, 4290, 4297, 4306, 4307, 4308, 4316, 4317, 4318, 4325, 4334, 4344, 4345, 4346, 4357, 4358, 4359, 4368, 4377, 4387, 4388, 4389, 4398, 4405, 4413, 4414, 4415, 4424, 4425, 4426, 4435, 4436, 4437, 4446, 4447, 4448, 4456, 4465, 4466, 4467, 4477, 4478, 4479, 4487, 4494, 4503, 4504, 4505, 4514, 4515, 4516, 4528, 4529, 4530, 4537, 4545, 4554, 4555, 4556, 4564, 4565, 4566, 4577, 4578, 4579, 4588, 4596, 4604, 4613, 4614, 4615, 4623, 4624, 4625, 4634, 4643, 4652, 4661, 4669, 4677, 4678, 4679, 4690, 4691, 4692, 4701, 4710, 4719, 4728, 4737, 4746, 4747, 4748, 4757, 4758, 4759, 4768, 4769, 4770, 4781, 4782, 4783, 4791, 4800, 4801, 4802, 4813, 4814, 4815, 4822, 4831, 4832, 4833, 4844, 4845, 4846, 4852, 4862, 4863, 4864, 4865, 4867, 4868, 4875, 4882, 4890, 4891, 4892, 4899, 4906, 4914, 4915, 4916, 4924, 4933, 4943, 4944, 4945, 4954, 4964, 4965, 4966, 4974, 4982, 4991, 5000, 5009, 5010, 5011, 5023, 5024, 5025, 5032, 5042, 5043, 5044, 5045, 5047, 5048, 5055, 5062, 5069, 5076, 5084, 5085, 5086, 5095, 5096, 5097, 5104, 5112, 5119, 5128, 5129, 5130, 5139, 5140, 5141, 5149, 5158, 5165, 5175, 5176, 5177, 5178, 5180, 5181, 5188, 5196, 5197, 5198, 5208, 5209, 5210, 5217, 5225, 5226, 5227, 5235, 5236, 5237, 5244, 5253, 5263, 5264, 5265, 5274, 5283, 5291, 5292, 5293, 5302, 5311, 5320, 5329, 5337, 5345, 5355, 5356, 5357, 5368, 5369, 5370, 5379, 5388, 5397, 5407, 5408, 5409, 5418, 5428, 5429, 5430, 5437, 5445, 5446, 5447, 5457, 5458, 5459, 5467, 5476, 5477, 5478, 5490, 5491, 5492, 5501, 5510, 5517, 5525, 5526, 5527, 5535, 5536, 5537, 5546, 5557, 5558, 5559, 5568, 5569, 5570, 5577, 5586, 5587, 5588, 5599, 5600, 5601, 5610, 5618, 5626, 5627, 5628, 5635, 5645, 5646, 5647, 5648, 5650, 5651, 5658, 5665, 5672, 5679, 5687, 5688, 5689, 5698, 5699, 5700, 5707, 5715, 5722, 5731, 5732, 5733, 5742, 5743, 5744, 5752, 5761, 5768, 5778, 5779, 5780, 5781, 5783, 5784, 5791, 5798, 5805, 5813, 5814, 5815, 5822, 5829, 5837, 5838, 5839, 5847, 5856, 5866, 5867, 5868, 5877, 5884, 5893, 5902, 5912, 5920, 5928, 5935, 5944, 5953, 5960, 5969, 5978, 5987, 5988, 5989, 6000, 6001, 6002, 6011, 6020, 6029, 6036, 6045, 6053, 6062, 6063, 6064, 6075, 6076, 6077, 6086, 6093, 6103, 6104, 6105, 6114, 6124, 6125, 6126, 6134, 6142, 6150, 6158, 6166, 6174, 6183, 6184, 6185, 6193, 6201, 6209, 6217, 6225, 6233, 6242, 6243, 6244, 6251, 6259, 6260, 6261, 6272, 6273, 6274, 6283, 6292, 6301, 6310, 6318, 6326, 6334, 6341, 6349, 6357, 6365, 6373, 6381, 6389, 6397, 6405, 6413, 6423, 6424, 6425, 6436, 6437, 6438, 6446, 6455, 6464, 6471, 6480, 6481, 6482, 6493, 6494, 6495, 6504, 6512, 6520, 6529, 6530, 6531, 6541, 6549, 6550, 6551, 6558, 6566, 6575, 6576, 6577, 6585, 6593, 6601, 6608, 6616, 6617, 6618, 6629, 6630, 6631, 6640, 6650, 6657, 6664, 6673, 6680, 6689, 6697, 6705, 6714, 6715, 6716, 6724, 6732, 6741, 6749, 6757, 6758, 6759, 6766, 6773, 6782, 6783, 6784, 6793, 6801, 6802, 6803, 6815, 6816, 6817, 6826, 6835, 6845, 6846, 6847, 6857, 6858, 6859, 6868, 6877, 6887, 6895, 6904, 6905, 6906, 6917, 6918, 6919, 6928, 6935, 6943, 6944, 6945, 6954, 6964, 6965, 6966, 6974, 6982, 6990, 6998, 7006, 7014, 7023, 7024, 7025, 7033, 7041, 7049, 7057, 7065, 7073, 7082, 7083, 7084, 7091, 7099, 7107, 7115, 7124, 7125, 7126, 7133, 7141, 7149, 7158, 7159, 7160, 7168, 7169, 7170, 7178, 7186, 7194, 7203, 7212, 7213, 7214, 7222, 7230, 7239, 7247, 7255, 7256, 7257, 7264, 7271, 7281, 7282, 7283, 7284, 7286, 7287, 7294, 7301, 7308, 7315, 7323, 7324, 7325, 7334, 7335, 7336, 7343, 7351, 7358, 7367, 7368, 7369, 7378, 7379, 7380, 7388, 7397, 7404, 7414, 7415, 7416, 7417, 7419, 7420, 7427, 7434, 7441, 7448, 7455, 7463, 7464, 7465, 7474, 7475, 7476, 7483, 7491, 7498, 7507, 7508, 7509, 7518, 7519, 7520, 7528, 7537, 7544, 7553, 7554, 7555, 7563, 7572, 7582, 7583, 7584, 7593, 7600, 7609, 7616, 7626, 7634, 7642, 7649, 7658, 7667, 7674, 7683, 7692, 7701, 7702, 7703, 7714, 7715, 7716, 7725, 7734, 7743, 7750, 7759, 7767, 7776, 7777, 7778, 7789, 7790, 7791, 7800, 7807, 7817, 7818, 7819, 7828, 7838, 7839, 7840, 7848, 7856, 7864, 7872, 7880, 7888, 7897, 7898, 7899, 7907, 7915, 7923, 7931, 7939, 7947, 7956, 7957, 7958, 7965, 7973, 7974, 7975, 7984, 7985, 7986, 7995, 8004, 8013, 8022, 8030, 8038, 8046, 8053, 8061, 8069, 8077, 8085, 8093, 8101, 8109, 8117, 8125, 8135, 8136, 8137, 8148, 8149, 8150, 8158, 8167, 8176, 8183, 8192, 8193, 8194, 8205, 8206, 8207, 8216, 8224, 8232, 8241, 8242, 8243, 8253, 8261, 8262, 8263, 8270, 8278, 8287, 8288, 8289, 8297, 8305, 8313, 8320, 8328, 8329, 8330, 8341, 8342, 8343, 8352, 8362, 8369, 8376, 8385, 8392, 8401, 8409, 8417, 8426, 8427, 8428, 8436, 8444, 8453, 8461, 8469, 8470, 8471, 8478, 8485, 8494, 8495, 8496, 8505, 8513, 8514, 8515, 8527, 8528, 8529, 8538, 8547, 8557, 8558, 8559, 8569, 8570, 8571, 8580, 8589, 8599, 8607, 8616, 8617, 8618, 8629, 8630, 8631, 8640, 8647, 8655, 8656, 8657, 8666, 8676, 8677, 8678, 8686, 8694, 8702, 8710, 8718, 8726, 8735, 8736, 8737, 8745, 8753, 8761, 8769, 8777, 8785, 8794, 8795, 8796, 8803, 8811, 8819, 8827, 8836, 8837, 8838, 8845, 8853, 8861, 8870, 8871, 8872, 8880, 8881, 8882, 8890, 8898, 8906, 8915, 8924, 8925, 8926, 8934, 8942, 8951, 8959, 8967, 8968, 8969, 8976, 8983, 8993, 8994, 8995, 8996, 8998, 8999, 9006, 9013, 9021, 9022, 9023, 9033, 9034, 9035, 9042, 9051, 9060, 9069, 9078, 9086, 9094, 9101, 9110, 9111, 9112, 9119, 9129, 9130, 9131, 9142, 9143, 9144, 9153, 9162, 9171, 9180, 9187, 9196, 9205, 9214, 9224, 9225, 9226, 9234, 9235, 9236, 9245, 9253, 9261, 9262, 9263, 9271, 9272, 9273, 9282, 9291, 9301, 9302, 9303, 9312, 9321, 9322, 9323, 9332, 9342, 9343, 9344, 9353, 9361, 9362, 9363, 9371, 9372, 9373, 9380, 9389, 9399, 9400, 9401, 9412, 9413, 9414, 9424, 9432, 9440, 9448, 9455, 9464, 9465, 9466, 9475, 9485, 9486, 9487, 9498, 9499, 9500, 9508, 9517, 9518, 9519, 9528, 9536, 9544, 9553, 9554, 9555, 9563, 9572, 9573, 9574, 9582, 9583, 9584, 9592, 9593, 9594, 9602, 9603, 9604, 9613, 9620, 9628, 9637, 9638, 9639, 9647, 9655, 9664, 9665, 9666, 9675, 9685, 9686, 9687, 9698, 9699, 9700, 9709, 9710, 9711, 9722, 9723, 9724, 9731, 9740, 9747, 9754, 9763, 9771, 9778, 9785, 9794, 9795, 9796, 9805, 9814, 9823, 9830, 9840, 9841, 9842, 9854, 9855, 9856, 9864, 9873, 9874, 9875, 9883, 9892, 9893, 9894, 9902, 9903, 9904, 9912, 9913, 9914, 9921, 9929, 9930, 9931, 9940, 9950, 9951, 9952, 9960, 9961, 9962, 9969, 9977, 9978, 9979, 9987, 9988, 9989, 9997, 9998, 9999, 10007, 10008, 10009, 10017, 10018, 10019, 10027, 10028, 10029, 10036, 10045, 10054, 10063, 10071, 10079, 10088, 10089, 10090, 10099, 10108, 10117, 10127, 10128, 10129, 10137, 10146, 10147, 10148, 10155, 10164, 10165, 10166, 10175, 10184, 10193, 10202, 10211, 10212, 10213, 10222, 10223, 10224, 10233, 10242, 10251, 10260, 10269, 10278, 10286, 10287, 10288, 10300, 10301, 10302, 10311, 10319, 10327, 10328, 10329, 10336, 10344, 10353, 10354, 10355, 10366, 10367, 10368, 10377, 10386, 10394, 10395, 10396, 10402, 10410, 10411, 10412, 10423, 10424, 10425, 10432, 10441, 10448, 10456, 10457, 10458, 10466, 10467, 10468, 10477, 10486, 10495, 10502, 10509, 10517, 10518, 10519, 10528, 10537, 10545, 10554, 10555, 10556, 10564, 10572, 10581, 10582, 10583, 10592, 10600, 10601, 10602, 10610, 10619, 10620, 10621, 10629, 10639, 10640, 10641, 10650, 10660, 10661, 10662, 10670, 10671, 10672, 10680, 10681, 10682, 10691, 10692, 10693, 10704, 10705, 10706, 10714, 10723, 10732, 10742, 10743, 10744, 10752, 10753, 10754, 10762, 10763, 10764, 10771, 10779, 10780, 10781, 10788, 10797, 10806, 10815, 10816, 10817, 10824, 10832, 10841, 10842, 10843, 10852, 10861, 10870, 10878, 10879, 10880, 10889, 10890, 10891, 10899, 10908, 10909, 10910, 10919, 10930, 10931, 10932, 10933, 10935, 10936, 10943, 10950, 10957, 10964, 10971, 10979, 10980, 10981, 10990, 10991, 10992, 10999, 11007, 11014, 11023, 11024, 11025, 11034, 11035, 11036, 11044, 11052, 11061, 11068, 11077, 11078, 11079, 11090, 11091, 11092, 11100, 11101, 11102, 11109, 11120, 11121, 11122, 11123, 11125, 11126, 11133, 11140, 11147, 11154, 11162, 11163, 11164, 11173, 11174, 11175, 11183, 11191, 11200, 11207, 11216, 11217, 11218, 11226, 11227, 11228, 11236, 11237, 11238, 11249, 11250, 11251, 11259, 11260, 11261, 11268, 11279, 11280, 11281, 11282, 11284, 11285, 11292, 11299, 11306, 11313, 11321, 11322, 11323, 11332, 11333, 11334, 11341, 11349, 11356, 11365, 11366, 11367, 11376, 11377, 11378, 11386, 11395, 11402, 11412, 11413, 11414, 11415, 11417, 11418, 11425, 11432, 11439, 11447, 11454, 11462, 11463, 11464, 11473, 11474, 11475, 11482, 11490, 11497, 11506, 11507, 11508, 11517, 11518, 11519, 11527, 11534, 11544, 11545, 11546, 11547, 11549, 11550, 11557, 11564, 11571, 11578, 11585, 11593, 11594, 11595, 11604, 11605, 11606, 11613, 11621, 11628, 11637, 11638, 11639, 11648, 11649, 11650, 11658, 11666, 11675, 11682, 11691, 11692, 11693, 11703, 11704, 11705, 11714, 11723, 11732, 11741, 11750, 11758, 11766, 11773, 11782, 11783, 11784, 11791, 11801, 11802, 11803, 11814, 11815, 11816, 11825, 11834, 11843, 11852, 11859, 11868, 11877, 11886, 11896, 11897, 11898, 11906, 11907, 11908, 11917, 11925, 11933, 11934, 11935, 11943, 11944, 11945, 11954, 11963, 11973, 11974, 11975, 11984, 11993, 11994, 11995, 12004, 12014, 12015, 12016, 12025, 12033, 12034, 12035, 12043, 12044, 12045, 12052, 12061, 12071, 12072, 12073, 12084, 12085, 12086, 12096, 12104, 12112, 12120, 12127, 12136, 12137, 12138, 12147, 12157, 12158, 12159, 12170, 12171, 12172, 12180, 12189, 12190, 12191, 12200, 12208, 12216, 12225, 12226, 12227, 12235, 12244, 12245, 12246, 12254, 12255, 12256, 12264, 12265, 12266, 12274, 12275, 12276, 12285, 12292, 12300, 12309, 12310, 12311, 12319, 12327, 12336, 12337, 12338, 12347, 12357, 12358, 12359, 12370, 12371, 12372, 12381, 12382, 12383, 12394, 12395, 12396, 12403, 12412, 12419, 12426, 12435, 12443, 12450, 12457, 12466, 12467, 12468, 12477, 12486, 12495, 12502, 12512, 12513, 12514, 12526, 12527, 12528, 12536, 12545, 12546, 12547, 12555, 12564, 12565, 12566, 12574, 12575, 12576, 12584, 12585, 12586, 12593, 12601, 12602, 12603, 12612, 12622, 12623, 12624, 12632, 12633, 12634, 12641, 12649, 12650, 12651, 12659, 12660, 12661, 12669, 12670, 12671, 12679, 12680, 12681, 12689, 12690, 12691, 12699, 12700, 12701, 12708, 12717, 12726, 12735, 12743, 12751, 12760, 12761, 12762, 12771, 12780, 12789, 12799, 12800, 12801, 12809, 12818, 12819, 12820, 12827, 12836, 12837, 12838, 12847, 12856, 12865, 12874, 12883, 12884, 12885, 12894, 12895, 12896, 12905, 12914, 12923, 12932, 12941, 12950, 12958, 12959, 12960, 12972, 12973, 12974, 12983, 12991, 12999, 13000, 13001, 13008, 13016, 13025, 13026, 13027, 13038, 13039, 13040, 13049, 13058, 13066, 13067, 13068, 13074, 13082, 13083, 13084, 13095, 13096, 13097, 13104, 13113, 13120, 13128, 13129, 13130, 13138, 13139, 13140, 13149, 13158, 13167, 13174, 13181, 13189, 13190, 13191, 13200, 13209, 13217, 13226, 13227, 13228, 13236, 13244, 13253, 13254, 13255, 13264, 13272, 13273, 13274, 13282, 13291, 13292, 13293, 13301, 13311, 13312, 13313, 13322, 13332, 13333, 13334, 13342, 13343, 13344, 13352, 13353, 13354, 13363, 13364, 13365, 13376, 13377, 13378, 13386, 13395, 13404, 13414, 13415, 13416, 13424, 13425, 13426, 13434, 13435, 13436, 13443, 13451, 13452, 13453, 13460, 13469, 13478, 13487, 13488, 13489, 13496, 13504, 13513, 13514, 13515, 13524, 13533, 13542, 13550, 13551, 13552, 13561, 13562, 13563, 13571, 13580, 13581, 13582, 13591], "summary": {"covered_lines": 2756, "num_statements": 2756, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": [], "functions": {"": {"executed_lines": [1, 2, 3, 5, 6, 7, 9, 12, 13, 14, 17, 18, 21, 22, 23, 24, 25, 28, 29, 30, 31, 34, 35, 38, 39, 40, 41, 42, 43, 46, 47, 48, 51, 52, 55, 56, 59, 60, 63, 64, 65, 68, 69, 72, 73, 76, 77, 78, 79, 80, 83, 84, 85, 86, 87, 88, 89, 92, 93, 94, 95, 98, 99, 100, 101, 102, 105, 106, 107, 108, 111, 112, 115, 116, 117, 118, 119, 120, 123, 124, 125, 128, 129, 130, 131, 132, 135, 136, 137, 138, 141, 142, 143, 144, 146, 147, 154, 161, 169, 170, 171, 179, 180, 181, 190, 201, 202, 203, 204, 206, 207, 214, 221, 229, 230, 231, 239, 240, 241, 248, 257, 265, 266, 267, 275, 284, 285, 286, 297, 298, 299, 308, 318, 319, 320, 329, 340, 341, 342, 343, 345, 346, 354, 361, 370, 371, 372, 373, 375, 376, 383, 390, 398, 399, 400, 408, 409, 410, 419, 428, 438, 439, 440, 450, 451, 452, 455, 456, 459, 460, 461, 464, 465, 468, 469, 472, 473, 474, 475, 476, 479, 480, 483, 484, 487, 488, 491, 492, 493, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 508, 509, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 524, 525, 526, 527, 528, 529, 532, 533, 536, 537, 538, 541, 542, 543, 546, 547, 548, 551, 552, 553, 554, 555, 556, 557, 558, 561, 562, 563, 566, 567, 570, 571, 574, 575, 578, 579, 582, 583, 584, 587, 588, 590, 591, 592, 593, 594, 595, 596, 597, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 612, 613, 616, 617, 620, 621, 622, 625, 626, 627, 630, 631, 634, 635, 636, 637, 638, 639, 640, 643, 644, 647, 648, 649, 650, 651, 654, 655, 656, 657, 659, 660, 667, 674, 682, 683, 684, 692, 693, 694, 703, 712, 721, 730, 739, 748, 757, 766, 775, 776, 777, 786, 795, 804, 813, 822, 823, 824, 832, 833, 834, 842, 852, 853, 854, 862, 863, 864, 875, 876, 877, 886, 895, 904, 912, 913, 914, 924, 925, 926, 936, 945, 955, 956, 957, 964, 971, 980, 981, 982, 993, 994, 995, 1002, 1011, 1019, 1020, 1021, 1029, 1038, 1047, 1056, 1064, 1073, 1074, 1075, 1082, 1089, 1098, 1099, 1100, 1111, 1112, 1113, 1120, 1129, 1137, 1138, 1139, 1147, 1156, 1165, 1174, 1183, 1184, 1185, 1192, 1199, 1208, 1209, 1210, 1217, 1224, 1231, 1239, 1240, 1241, 1251, 1252, 1253, 1262, 1270, 1277, 1285, 1294, 1295, 1296, 1306, 1307, 1308, 1317, 1318, 1319, 1327, 1328, 1329, 1339, 1340, 1341, 1348, 1357, 1366, 1375, 1383, 1391, 1399, 1409, 1410, 1411, 1419, 1427, 1436, 1444, 1452, 1453, 1454, 1465, 1466, 1467, 1476, 1477, 1478, 1488, 1489, 1490, 1499, 1508, 1518, 1519, 1520, 1528, 1529, 1530, 1541, 1542, 1543, 1550, 1557, 1566, 1567, 1568, 1579, 1580, 1581, 1588, 1597, 1606, 1607, 1608, 1616, 1626, 1627, 1628, 1635, 1642, 1651, 1652, 1653, 1664, 1665, 1666, 1675, 1684, 1693, 1702, 1711, 1720, 1730, 1731, 1732, 1740, 1741, 1742, 1750, 1751, 1752, 1763, 1764, 1765, 1772, 1779, 1788, 1789, 1790, 1798, 1799, 1800, 1807, 1816, 1825, 1834, 1835, 1836, 1847, 1848, 1849, 1856, 1863, 1872, 1873, 1874, 1882, 1883, 1884, 1891, 1899, 1908, 1916, 1925, 1934, 1935, 1936, 1947, 1948, 1949, 1956, 1963, 1972, 1973, 1974, 1982, 1983, 1984, 1991, 2000, 2009, 2017, 2024, 2033, 2041, 2042, 2043, 2054, 2055, 2056, 2063, 2070, 2079, 2080, 2081, 2089, 2090, 2091, 2098, 2107, 2117, 2118, 2119, 2130, 2131, 2132, 2141, 2150, 2160, 2161, 2162, 2171, 2178, 2186, 2187, 2188, 2197, 2198, 2199, 2208, 2209, 2210, 2219, 2220, 2221, 2229, 2238, 2239, 2240, 2250, 2251, 2252, 2260, 2267, 2276, 2277, 2278, 2287, 2288, 2289, 2301, 2302, 2303, 2310, 2318, 2327, 2328, 2329, 2337, 2338, 2339, 2350, 2351, 2352, 2361, 2369, 2377, 2386, 2387, 2388, 2396, 2397, 2398, 2407, 2416, 2425, 2434, 2442, 2450, 2451, 2452, 2463, 2464, 2465, 2474, 2483, 2492, 2501, 2510, 2519, 2520, 2521, 2530, 2531, 2532, 2541, 2542, 2543, 2554, 2555, 2556, 2564, 2573, 2574, 2575, 2586, 2587, 2588, 2595, 2604, 2605, 2606, 2617, 2618, 2619, 2625, 2635, 2636, 2637, 2638, 2640, 2641, 2648, 2655, 2662, 2669, 2677, 2678, 2679, 2688, 2689, 2690, 2697, 2705, 2712, 2721, 2722, 2723, 2732, 2733, 2734, 2742, 2751, 2758, 2768, 2769, 2770, 2771, 2773, 2774, 2781, 2788, 2795, 2804, 2811, 2819, 2820, 2821, 2830, 2831, 2832, 2839, 2847, 2854, 2863, 2864, 2865, 2874, 2875, 2876, 2884, 2893, 2900, 2909, 2910, 2911, 2919, 2920, 2921, 2930, 2939, 2948, 2957, 2966, 2975, 2984, 2993, 3002, 3003, 3004, 3013, 3022, 3031, 3040, 3049, 3050, 3051, 3059, 3060, 3061, 3069, 3079, 3080, 3081, 3089, 3090, 3091, 3102, 3103, 3104, 3113, 3122, 3131, 3139, 3140, 3141, 3151, 3152, 3153, 3163, 3172, 3182, 3183, 3184, 3191, 3198, 3207, 3208, 3209, 3220, 3221, 3222, 3229, 3238, 3246, 3247, 3248, 3256, 3265, 3274, 3283, 3291, 3300, 3301, 3302, 3309, 3316, 3325, 3326, 3327, 3338, 3339, 3340, 3347, 3356, 3364, 3365, 3366, 3374, 3383, 3392, 3401, 3410, 3411, 3412, 3419, 3426, 3435, 3436, 3437, 3444, 3451, 3458, 3466, 3467, 3468, 3478, 3479, 3480, 3489, 3497, 3504, 3512, 3521, 3522, 3523, 3533, 3534, 3535, 3544, 3545, 3546, 3554, 3555, 3556, 3566, 3567, 3568, 3575, 3584, 3593, 3602, 3610, 3618, 3626, 3636, 3637, 3638, 3646, 3654, 3663, 3671, 3679, 3680, 3681, 3692, 3693, 3694, 3703, 3704, 3705, 3715, 3716, 3717, 3726, 3735, 3745, 3746, 3747, 3755, 3756, 3757, 3768, 3769, 3770, 3777, 3784, 3793, 3794, 3795, 3806, 3807, 3808, 3815, 3824, 3833, 3834, 3835, 3843, 3853, 3854, 3855, 3862, 3869, 3878, 3879, 3880, 3891, 3892, 3893, 3902, 3911, 3920, 3929, 3938, 3947, 3957, 3958, 3959, 3967, 3968, 3969, 3977, 3978, 3979, 3990, 3991, 3992, 3999, 4006, 4015, 4016, 4017, 4025, 4026, 4027, 4034, 4043, 4052, 4061, 4062, 4063, 4074, 4075, 4076, 4083, 4090, 4099, 4100, 4101, 4109, 4110, 4111, 4118, 4126, 4135, 4143, 4152, 4161, 4162, 4163, 4174, 4175, 4176, 4183, 4190, 4199, 4200, 4201, 4209, 4210, 4211, 4218, 4227, 4236, 4244, 4251, 4260, 4268, 4269, 4270, 4281, 4282, 4283, 4290, 4297, 4306, 4307, 4308, 4316, 4317, 4318, 4325, 4334, 4344, 4345, 4346, 4357, 4358, 4359, 4368, 4377, 4387, 4388, 4389, 4398, 4405, 4413, 4414, 4415, 4424, 4425, 4426, 4435, 4436, 4437, 4446, 4447, 4448, 4456, 4465, 4466, 4467, 4477, 4478, 4479, 4487, 4494, 4503, 4504, 4505, 4514, 4515, 4516, 4528, 4529, 4530, 4537, 4545, 4554, 4555, 4556, 4564, 4565, 4566, 4577, 4578, 4579, 4588, 4596, 4604, 4613, 4614, 4615, 4623, 4624, 4625, 4634, 4643, 4652, 4661, 4669, 4677, 4678, 4679, 4690, 4691, 4692, 4701, 4710, 4719, 4728, 4737, 4746, 4747, 4748, 4757, 4758, 4759, 4768, 4769, 4770, 4781, 4782, 4783, 4791, 4800, 4801, 4802, 4813, 4814, 4815, 4822, 4831, 4832, 4833, 4844, 4845, 4846, 4852, 4862, 4863, 4864, 4865, 4867, 4868, 4875, 4882, 4890, 4891, 4892, 4899, 4906, 4914, 4915, 4916, 4924, 4933, 4943, 4944, 4945, 4954, 4964, 4965, 4966, 4974, 4982, 4991, 5000, 5009, 5010, 5011, 5023, 5024, 5025, 5032, 5042, 5043, 5044, 5045, 5047, 5048, 5055, 5062, 5069, 5076, 5084, 5085, 5086, 5095, 5096, 5097, 5104, 5112, 5119, 5128, 5129, 5130, 5139, 5140, 5141, 5149, 5158, 5165, 5175, 5176, 5177, 5178, 5180, 5181, 5188, 5196, 5197, 5198, 5208, 5209, 5210, 5217, 5225, 5226, 5227, 5235, 5236, 5237, 5244, 5253, 5263, 5264, 5265, 5274, 5283, 5291, 5292, 5293, 5302, 5311, 5320, 5329, 5337, 5345, 5355, 5356, 5357, 5368, 5369, 5370, 5379, 5388, 5397, 5407, 5408, 5409, 5418, 5428, 5429, 5430, 5437, 5445, 5446, 5447, 5457, 5458, 5459, 5467, 5476, 5477, 5478, 5490, 5491, 5492, 5501, 5510, 5517, 5525, 5526, 5527, 5535, 5536, 5537, 5546, 5557, 5558, 5559, 5568, 5569, 5570, 5577, 5586, 5587, 5588, 5599, 5600, 5601, 5610, 5618, 5626, 5627, 5628, 5635, 5645, 5646, 5647, 5648, 5650, 5651, 5658, 5665, 5672, 5679, 5687, 5688, 5689, 5698, 5699, 5700, 5707, 5715, 5722, 5731, 5732, 5733, 5742, 5743, 5744, 5752, 5761, 5768, 5778, 5779, 5780, 5781, 5783, 5784, 5791, 5798, 5805, 5813, 5814, 5815, 5822, 5829, 5837, 5838, 5839, 5847, 5856, 5866, 5867, 5868, 5877, 5884, 5893, 5902, 5912, 5920, 5928, 5935, 5944, 5953, 5960, 5969, 5978, 5987, 5988, 5989, 6000, 6001, 6002, 6011, 6020, 6029, 6036, 6045, 6053, 6062, 6063, 6064, 6075, 6076, 6077, 6086, 6093, 6103, 6104, 6105, 6114, 6124, 6125, 6126, 6134, 6142, 6150, 6158, 6166, 6174, 6183, 6184, 6185, 6193, 6201, 6209, 6217, 6225, 6233, 6242, 6243, 6244, 6251, 6259, 6260, 6261, 6272, 6273, 6274, 6283, 6292, 6301, 6310, 6318, 6326, 6334, 6341, 6349, 6357, 6365, 6373, 6381, 6389, 6397, 6405, 6413, 6423, 6424, 6425, 6436, 6437, 6438, 6446, 6455, 6464, 6471, 6480, 6481, 6482, 6493, 6494, 6495, 6504, 6512, 6520, 6529, 6530, 6531, 6541, 6549, 6550, 6551, 6558, 6566, 6575, 6576, 6577, 6585, 6593, 6601, 6608, 6616, 6617, 6618, 6629, 6630, 6631, 6640, 6650, 6657, 6664, 6673, 6680, 6689, 6697, 6705, 6714, 6715, 6716, 6724, 6732, 6741, 6749, 6757, 6758, 6759, 6766, 6773, 6782, 6783, 6784, 6793, 6801, 6802, 6803, 6815, 6816, 6817, 6826, 6835, 6845, 6846, 6847, 6857, 6858, 6859, 6868, 6877, 6887, 6895, 6904, 6905, 6906, 6917, 6918, 6919, 6928, 6935, 6943, 6944, 6945, 6954, 6964, 6965, 6966, 6974, 6982, 6990, 6998, 7006, 7014, 7023, 7024, 7025, 7033, 7041, 7049, 7057, 7065, 7073, 7082, 7083, 7084, 7091, 7099, 7107, 7115, 7124, 7125, 7126, 7133, 7141, 7149, 7158, 7159, 7160, 7168, 7169, 7170, 7178, 7186, 7194, 7203, 7212, 7213, 7214, 7222, 7230, 7239, 7247, 7255, 7256, 7257, 7264, 7271, 7281, 7282, 7283, 7284, 7286, 7287, 7294, 7301, 7308, 7315, 7323, 7324, 7325, 7334, 7335, 7336, 7343, 7351, 7358, 7367, 7368, 7369, 7378, 7379, 7380, 7388, 7397, 7404, 7414, 7415, 7416, 7417, 7419, 7420, 7427, 7434, 7441, 7448, 7455, 7463, 7464, 7465, 7474, 7475, 7476, 7483, 7491, 7498, 7507, 7508, 7509, 7518, 7519, 7520, 7528, 7537, 7544, 7553, 7554, 7555, 7563, 7572, 7582, 7583, 7584, 7593, 7600, 7609, 7616, 7626, 7634, 7642, 7649, 7658, 7667, 7674, 7683, 7692, 7701, 7702, 7703, 7714, 7715, 7716, 7725, 7734, 7743, 7750, 7759, 7767, 7776, 7777, 7778, 7789, 7790, 7791, 7800, 7807, 7817, 7818, 7819, 7828, 7838, 7839, 7840, 7848, 7856, 7864, 7872, 7880, 7888, 7897, 7898, 7899, 7907, 7915, 7923, 7931, 7939, 7947, 7956, 7957, 7958, 7965, 7973, 7974, 7975, 7984, 7985, 7986, 7995, 8004, 8013, 8022, 8030, 8038, 8046, 8053, 8061, 8069, 8077, 8085, 8093, 8101, 8109, 8117, 8125, 8135, 8136, 8137, 8148, 8149, 8150, 8158, 8167, 8176, 8183, 8192, 8193, 8194, 8205, 8206, 8207, 8216, 8224, 8232, 8241, 8242, 8243, 8253, 8261, 8262, 8263, 8270, 8278, 8287, 8288, 8289, 8297, 8305, 8313, 8320, 8328, 8329, 8330, 8341, 8342, 8343, 8352, 8362, 8369, 8376, 8385, 8392, 8401, 8409, 8417, 8426, 8427, 8428, 8436, 8444, 8453, 8461, 8469, 8470, 8471, 8478, 8485, 8494, 8495, 8496, 8505, 8513, 8514, 8515, 8527, 8528, 8529, 8538, 8547, 8557, 8558, 8559, 8569, 8570, 8571, 8580, 8589, 8599, 8607, 8616, 8617, 8618, 8629, 8630, 8631, 8640, 8647, 8655, 8656, 8657, 8666, 8676, 8677, 8678, 8686, 8694, 8702, 8710, 8718, 8726, 8735, 8736, 8737, 8745, 8753, 8761, 8769, 8777, 8785, 8794, 8795, 8796, 8803, 8811, 8819, 8827, 8836, 8837, 8838, 8845, 8853, 8861, 8870, 8871, 8872, 8880, 8881, 8882, 8890, 8898, 8906, 8915, 8924, 8925, 8926, 8934, 8942, 8951, 8959, 8967, 8968, 8969, 8976, 8983, 8993, 8994, 8995, 8996, 8998, 8999, 9006, 9013, 9021, 9022, 9023, 9033, 9034, 9035, 9042, 9051, 9060, 9069, 9078, 9086, 9094, 9101, 9110, 9111, 9112, 9119, 9129, 9130, 9131, 9142, 9143, 9144, 9153, 9162, 9171, 9180, 9187, 9196, 9205, 9214, 9224, 9225, 9226, 9234, 9235, 9236, 9245, 9253, 9261, 9262, 9263, 9271, 9272, 9273, 9282, 9291, 9301, 9302, 9303, 9312, 9321, 9322, 9323, 9332, 9342, 9343, 9344, 9353, 9361, 9362, 9363, 9371, 9372, 9373, 9380, 9389, 9399, 9400, 9401, 9412, 9413, 9414, 9424, 9432, 9440, 9448, 9455, 9464, 9465, 9466, 9475, 9485, 9486, 9487, 9498, 9499, 9500, 9508, 9517, 9518, 9519, 9528, 9536, 9544, 9553, 9554, 9555, 9563, 9572, 9573, 9574, 9582, 9583, 9584, 9592, 9593, 9594, 9602, 9603, 9604, 9613, 9620, 9628, 9637, 9638, 9639, 9647, 9655, 9664, 9665, 9666, 9675, 9685, 9686, 9687, 9698, 9699, 9700, 9709, 9710, 9711, 9722, 9723, 9724, 9731, 9740, 9747, 9754, 9763, 9771, 9778, 9785, 9794, 9795, 9796, 9805, 9814, 9823, 9830, 9840, 9841, 9842, 9854, 9855, 9856, 9864, 9873, 9874, 9875, 9883, 9892, 9893, 9894, 9902, 9903, 9904, 9912, 9913, 9914, 9921, 9929, 9930, 9931, 9940, 9950, 9951, 9952, 9960, 9961, 9962, 9969, 9977, 9978, 9979, 9987, 9988, 9989, 9997, 9998, 9999, 10007, 10008, 10009, 10017, 10018, 10019, 10027, 10028, 10029, 10036, 10045, 10054, 10063, 10071, 10079, 10088, 10089, 10090, 10099, 10108, 10117, 10127, 10128, 10129, 10137, 10146, 10147, 10148, 10155, 10164, 10165, 10166, 10175, 10184, 10193, 10202, 10211, 10212, 10213, 10222, 10223, 10224, 10233, 10242, 10251, 10260, 10269, 10278, 10286, 10287, 10288, 10300, 10301, 10302, 10311, 10319, 10327, 10328, 10329, 10336, 10344, 10353, 10354, 10355, 10366, 10367, 10368, 10377, 10386, 10394, 10395, 10396, 10402, 10410, 10411, 10412, 10423, 10424, 10425, 10432, 10441, 10448, 10456, 10457, 10458, 10466, 10467, 10468, 10477, 10486, 10495, 10502, 10509, 10517, 10518, 10519, 10528, 10537, 10545, 10554, 10555, 10556, 10564, 10572, 10581, 10582, 10583, 10592, 10600, 10601, 10602, 10610, 10619, 10620, 10621, 10629, 10639, 10640, 10641, 10650, 10660, 10661, 10662, 10670, 10671, 10672, 10680, 10681, 10682, 10691, 10692, 10693, 10704, 10705, 10706, 10714, 10723, 10732, 10742, 10743, 10744, 10752, 10753, 10754, 10762, 10763, 10764, 10771, 10779, 10780, 10781, 10788, 10797, 10806, 10815, 10816, 10817, 10824, 10832, 10841, 10842, 10843, 10852, 10861, 10870, 10878, 10879, 10880, 10889, 10890, 10891, 10899, 10908, 10909, 10910, 10919, 10930, 10931, 10932, 10933, 10935, 10936, 10943, 10950, 10957, 10964, 10971, 10979, 10980, 10981, 10990, 10991, 10992, 10999, 11007, 11014, 11023, 11024, 11025, 11034, 11035, 11036, 11044, 11052, 11061, 11068, 11077, 11078, 11079, 11090, 11091, 11092, 11100, 11101, 11102, 11109, 11120, 11121, 11122, 11123, 11125, 11126, 11133, 11140, 11147, 11154, 11162, 11163, 11164, 11173, 11174, 11175, 11183, 11191, 11200, 11207, 11216, 11217, 11218, 11226, 11227, 11228, 11236, 11237, 11238, 11249, 11250, 11251, 11259, 11260, 11261, 11268, 11279, 11280, 11281, 11282, 11284, 11285, 11292, 11299, 11306, 11313, 11321, 11322, 11323, 11332, 11333, 11334, 11341, 11349, 11356, 11365, 11366, 11367, 11376, 11377, 11378, 11386, 11395, 11402, 11412, 11413, 11414, 11415, 11417, 11418, 11425, 11432, 11439, 11447, 11454, 11462, 11463, 11464, 11473, 11474, 11475, 11482, 11490, 11497, 11506, 11507, 11508, 11517, 11518, 11519, 11527, 11534, 11544, 11545, 11546, 11547, 11549, 11550, 11557, 11564, 11571, 11578, 11585, 11593, 11594, 11595, 11604, 11605, 11606, 11613, 11621, 11628, 11637, 11638, 11639, 11648, 11649, 11650, 11658, 11666, 11675, 11682, 11691, 11692, 11693, 11703, 11704, 11705, 11714, 11723, 11732, 11741, 11750, 11758, 11766, 11773, 11782, 11783, 11784, 11791, 11801, 11802, 11803, 11814, 11815, 11816, 11825, 11834, 11843, 11852, 11859, 11868, 11877, 11886, 11896, 11897, 11898, 11906, 11907, 11908, 11917, 11925, 11933, 11934, 11935, 11943, 11944, 11945, 11954, 11963, 11973, 11974, 11975, 11984, 11993, 11994, 11995, 12004, 12014, 12015, 12016, 12025, 12033, 12034, 12035, 12043, 12044, 12045, 12052, 12061, 12071, 12072, 12073, 12084, 12085, 12086, 12096, 12104, 12112, 12120, 12127, 12136, 12137, 12138, 12147, 12157, 12158, 12159, 12170, 12171, 12172, 12180, 12189, 12190, 12191, 12200, 12208, 12216, 12225, 12226, 12227, 12235, 12244, 12245, 12246, 12254, 12255, 12256, 12264, 12265, 12266, 12274, 12275, 12276, 12285, 12292, 12300, 12309, 12310, 12311, 12319, 12327, 12336, 12337, 12338, 12347, 12357, 12358, 12359, 12370, 12371, 12372, 12381, 12382, 12383, 12394, 12395, 12396, 12403, 12412, 12419, 12426, 12435, 12443, 12450, 12457, 12466, 12467, 12468, 12477, 12486, 12495, 12502, 12512, 12513, 12514, 12526, 12527, 12528, 12536, 12545, 12546, 12547, 12555, 12564, 12565, 12566, 12574, 12575, 12576, 12584, 12585, 12586, 12593, 12601, 12602, 12603, 12612, 12622, 12623, 12624, 12632, 12633, 12634, 12641, 12649, 12650, 12651, 12659, 12660, 12661, 12669, 12670, 12671, 12679, 12680, 12681, 12689, 12690, 12691, 12699, 12700, 12701, 12708, 12717, 12726, 12735, 12743, 12751, 12760, 12761, 12762, 12771, 12780, 12789, 12799, 12800, 12801, 12809, 12818, 12819, 12820, 12827, 12836, 12837, 12838, 12847, 12856, 12865, 12874, 12883, 12884, 12885, 12894, 12895, 12896, 12905, 12914, 12923, 12932, 12941, 12950, 12958, 12959, 12960, 12972, 12973, 12974, 12983, 12991, 12999, 13000, 13001, 13008, 13016, 13025, 13026, 13027, 13038, 13039, 13040, 13049, 13058, 13066, 13067, 13068, 13074, 13082, 13083, 13084, 13095, 13096, 13097, 13104, 13113, 13120, 13128, 13129, 13130, 13138, 13139, 13140, 13149, 13158, 13167, 13174, 13181, 13189, 13190, 13191, 13200, 13209, 13217, 13226, 13227, 13228, 13236, 13244, 13253, 13254, 13255, 13264, 13272, 13273, 13274, 13282, 13291, 13292, 13293, 13301, 13311, 13312, 13313, 13322, 13332, 13333, 13334, 13342, 13343, 13344, 13352, 13353, 13354, 13363, 13364, 13365, 13376, 13377, 13378, 13386, 13395, 13404, 13414, 13415, 13416, 13424, 13425, 13426, 13434, 13435, 13436, 13443, 13451, 13452, 13453, 13460, 13469, 13478, 13487, 13488, 13489, 13496, 13504, 13513, 13514, 13515, 13524, 13533, 13542, 13550, 13551, 13552, 13561, 13562, 13563, 13571, 13580, 13581, 13582, 13591], "summary": {"covered_lines": 2756, "num_statements": 2756, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"BaseByGuestAmtType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "BookingRuleCodeContext": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "CommentName1": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "CommentName2": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ContactInfoLocation": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "DescriptionName": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "DescriptionTextFormat1": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "DescriptionTextFormat2": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "DiscountPercent": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ErrorStatus": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ErrorType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "EventIdType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "GuestFirstQualifyingPosition": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "HotelReservationResStatus": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ImageItemCategory": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "InvCountCountType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "LengthOfStayMinMaxMessageType1": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "LengthOfStayMinMaxMessageType2": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "LengthOfStayTimeUnit": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "MealsIncludedMealPlanCodes": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "MealsIncludedMealPlanIndicator": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "MultimediaDescriptionInfoCode1": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "MultimediaDescriptionInfoCode2": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRq": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRq.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRq.HotelDescriptiveInfos": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRq.HotelDescriptiveInfos.HotelDescriptiveInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRq": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRq.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRq.RatePlans": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRq.RatePlans.RatePlan": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRq.RatePlans.RatePlan.DateRange": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRq.RatePlans.RatePlan.RatePlanCandidates": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRq.RatePlans.RatePlan.RatePlanCandidates.RatePlanCandidate": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRq.RatePlans.RatePlan.HotelRef": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaPingRq": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaPingRq.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaReadRq": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaReadRq.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaReadRq.ReadRequests": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaReadRq.ReadRequests.HotelReadRequest": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaReadRq.ReadRequests.HotelReadRequest.SelectionCriteria": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OccupancyAgeQualifyingCode": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "PositionAltitudeUnitOfMeasureCode": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "PrerequisiteInventoryInvType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ProfileProfileType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "RateDescriptionName": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "RatePlanRatePlanNotifType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "RatePlanRatePlanType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "RateRateTimeUnit": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "RestrictionStatusRestriction": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "RestrictionStatusStatus": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "RoomTypeRoomType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ServiceMealPlanCode": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ServiceServiceCategoryCode": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ServiceServicePricingType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ServiceType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "SpecialRequestCodeContext": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "StayRequirementStayContext": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "SupplementAddToBasicRateIndicator": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "SupplementChargeTypeCode": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "SupplementInvType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "TaxPolicyChargeFrequency": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "TaxPolicyChargeUnit": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "TaxPolicyCode": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "TextTextFormat1": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "TextTextFormat2": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "TimeUnitType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "TypeRoomRoomType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "UrlType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "UniqueIdInstance": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "UniqueIdType1": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "UniqueIdType2": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "UniqueIdType3": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "VideoItemCategory": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "WarningStatus": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "DefSendComplete": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.CategoryCodes": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.CategoryCodes.HotelCategory": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.TextItems": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.TextItems.TextItem": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.TextItems.TextItem.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.ImageItems": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.ImageItems.ImageItem": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.ImageItems.ImageItem.ImageFormat": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.ImageItems.ImageItem.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.VideoItems": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.VideoItems.VideoItem": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.VideoItems.VideoItem.VideoFormat": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.VideoItems.VideoItem.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Position": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Services": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Services.Service": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Services.Service.Features": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Services.Service.Features.Feature": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.TypeRoom": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.Amenities": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.Amenities.Amenity": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions.MultimediaDescription": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions.MultimediaDescription.TextItems": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions.MultimediaDescription.TextItems.TextItem": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions.MultimediaDescription.TextItems.TextItem.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions.MultimediaDescription.ImageItems": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions.MultimediaDescription.ImageItems.ImageItem": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions.MultimediaDescription.ImageItems.ImageItem.ImageFormat": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions.MultimediaDescription.ImageItems.ImageItem.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.CancelPolicy": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.CancelPolicy.CancelPenalty": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.CancelPolicy.CancelPenalty.PenaltyDescription": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.CancelPolicy.CancelPenalty.PenaltyDescription.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.CheckoutCharges": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.CheckoutCharges.CheckoutCharge": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.CheckoutCharges.CheckoutCharge.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.CheckoutCharges.CheckoutCharge.Description.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.PetsPolicies": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.PetsPolicies.PetsPolicy": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.PetsPolicies.PetsPolicy.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.PetsPolicies.PetsPolicy.Description.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.TaxPolicies": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.TaxPolicies.TaxPolicy": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.TaxPolicies.TaxPolicy.TaxDescription": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.TaxPolicies.TaxPolicy.TaxDescription.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.AcceptedPayments": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.AcceptedPayments.AcceptedPayment": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.AcceptedPayments.AcceptedPayment.BankAcct": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.AcceptedPayments.AcceptedPayment.BankAcct.BankAcctNumber": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.AcceptedPayments.AcceptedPayment.BankAcct.BankId": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.AcceptedPayments.AcceptedPayment.Cash": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.AcceptedPayments.AcceptedPayment.PaymentCard": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.AmountPercent": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.Deadline": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.PolicyInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.StayRequirements": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.StayRequirements.StayRequirement": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.AffiliationInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.AffiliationInfo.Awards": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.AffiliationInfo.Awards.Award": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Addresses": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Addresses.Address": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Addresses.Address.StateProv": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Addresses.Address.CountryName": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Phones": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Phones.Phone": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Emails": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Emails.Email": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Urls": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRq.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Urls.Url": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRs": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRs.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRs.Errors": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRs.Errors.Error": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRs.Warnings": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveContentNotifRs.Warnings.Warning": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.Errors": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.Errors.Error": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.Warnings": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.Warnings.Warning": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.CategoryCodes": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.CategoryCodes.HotelCategory": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.TextItems": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.TextItems.TextItem": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.TextItems.TextItem.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.ImageItems": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.ImageItems.ImageItem": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.ImageItems.ImageItem.ImageFormat": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.ImageItems.ImageItem.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.VideoItems": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.VideoItems.VideoItem": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.VideoItems.VideoItem.VideoFormat": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Descriptions.MultimediaDescriptions.MultimediaDescription.VideoItems.VideoItem.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Position": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Services": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Services.Service": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Services.Service.Features": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.HotelInfo.Services.Service.Features.Feature": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.TypeRoom": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.Amenities": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.Amenities.Amenity": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions.MultimediaDescription": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions.MultimediaDescription.TextItems": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions.MultimediaDescription.TextItems.TextItem": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions.MultimediaDescription.TextItems.TextItem.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions.MultimediaDescription.ImageItems": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions.MultimediaDescription.ImageItems.ImageItem": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions.MultimediaDescription.ImageItems.ImageItem.ImageFormat": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.FacilityInfo.GuestRooms.GuestRoom.MultimediaDescriptions.MultimediaDescription.ImageItems.ImageItem.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.CancelPolicy": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.CancelPolicy.CancelPenalty": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.CancelPolicy.CancelPenalty.PenaltyDescription": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.CancelPolicy.CancelPenalty.PenaltyDescription.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.CheckoutCharges": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.CheckoutCharges.CheckoutCharge": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.CheckoutCharges.CheckoutCharge.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.CheckoutCharges.CheckoutCharge.Description.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.PetsPolicies": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.PetsPolicies.PetsPolicy": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.PetsPolicies.PetsPolicy.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.PetsPolicies.PetsPolicy.Description.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.TaxPolicies": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.TaxPolicies.TaxPolicy": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.TaxPolicies.TaxPolicy.TaxDescription": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.TaxPolicies.TaxPolicy.TaxDescription.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.AcceptedPayments": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.AcceptedPayments.AcceptedPayment": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.AcceptedPayments.AcceptedPayment.BankAcct": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.AcceptedPayments.AcceptedPayment.BankAcct.BankAcctNumber": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.AcceptedPayments.AcceptedPayment.BankAcct.BankId": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.AcceptedPayments.AcceptedPayment.Cash": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.AcceptedPayments.AcceptedPayment.PaymentCard": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.AmountPercent": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.GuaranteePaymentPolicy.GuaranteePayment.Deadline": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.PolicyInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.StayRequirements": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.Policies.Policy.StayRequirements.StayRequirement": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.AffiliationInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.AffiliationInfo.Awards": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.AffiliationInfo.Awards.Award": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Addresses": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Addresses.Address": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Addresses.Address.StateProv": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Addresses.Address.CountryName": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Phones": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Phones.Phone": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Emails": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Emails.Email": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Urls": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelDescriptiveInfoRs.HotelDescriptiveContents.HotelDescriptiveContent.ContactInfos.ContactInfo.Urls.Url": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelInvCountNotifRq": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelInvCountNotifRq.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelInvCountNotifRq.UniqueId": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelInvCountNotifRq.Inventories": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelInvCountNotifRq.Inventories.Inventory": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelInvCountNotifRq.Inventories.Inventory.StatusApplicationControl": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelInvCountNotifRq.Inventories.Inventory.InvCounts": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelInvCountNotifRq.Inventories.Inventory.InvCounts.InvCount": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelInvCountNotifRs": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelInvCountNotifRs.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelInvCountNotifRs.Errors": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelInvCountNotifRs.Errors.Error": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelInvCountNotifRs.Warnings": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelInvCountNotifRs.Warnings.Warning": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.EventSites": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.EventSites.EventSite": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.EventSites.EventSite.EventId": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.GeneralEventInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.GeneralEventInfo.EventContacts": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.GeneralEventInfo.EventContacts.EventContact": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.GeneralEventInfo.EventContacts.EventContact.PersonName": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.GeneralEventInfo.EventContacts.EventContact.Url": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.GeneralEventInfo.EventContacts.EventContact.EmployeeInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.GeneralEventInfo.AttendeeInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.GeneralEventInfo.Dates": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.GeneralEventInfo.Dates.Date": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.GeneralEventInfo.Dates.Date.EndDateWindow": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.GeneralEventInfo.Dates.Date.LocationCategories": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.GeneralEventInfo.Dates.Date.LocationCategories.Location": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.GeneralEventInfo.Dates.Date.LocationCategories.Category": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.GeneralEventInfo.Comments": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.GeneralEventInfo.Comments.Comment": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRq.EventReports.EventReport.GeneralEventInfo.Comments.Comment.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRs": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRs.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRs.Errors": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRs.Errors.Error": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRs.Warnings": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelPostEventNotifRs.Warnings.Warning": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.UniqueId": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.BookingRules": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.BookingRules.BookingRule": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.BookingRules.BookingRule.LengthsOfStay": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.BookingRules.BookingRule.LengthsOfStay.LengthOfStay": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.BookingRules.BookingRule.DowRestrictions": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.BookingRules.BookingRule.DowRestrictions.ArrivalDaysOfWeek": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.BookingRules.BookingRule.DowRestrictions.DepartureDaysOfWeek": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.BookingRules.BookingRule.RestrictionStatus": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Rates": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Rates.Rate": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Rates.Rate.BaseByGuestAmts": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Rates.Rate.BaseByGuestAmts.BaseByGuestAmt": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Rates.Rate.AdditionalGuestAmounts": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Rates.Rate.AdditionalGuestAmounts.AdditionalGuestAmount": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Rates.Rate.RateDescription": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Rates.Rate.RateDescription.ListItem": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Rates.Rate.MealsIncluded": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Supplements": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Supplements.Supplement": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Supplements.Supplement.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Supplements.Supplement.Description.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Supplements.Supplement.PrerequisiteInventory": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Offers": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Offers.Offer": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Offers.Offer.OfferRules": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Offers.Offer.OfferRules.OfferRule": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Offers.Offer.OfferRules.OfferRule.LengthsOfStay": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Offers.Offer.OfferRules.OfferRule.LengthsOfStay.LengthOfStay": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Offers.Offer.OfferRules.OfferRule.DowRestrictions": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Offers.Offer.OfferRules.OfferRule.DowRestrictions.ArrivalDaysOfWeek": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Offers.Offer.OfferRules.OfferRule.DowRestrictions.DepartureDaysOfWeek": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Offers.Offer.OfferRules.OfferRule.Occupancy": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Offers.Offer.Discount": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Offers.Offer.Guests": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Offers.Offer.Guests.Guest": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRq.RatePlans.RatePlan.Description.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRs": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRs.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRs.Errors": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRs.Errors.Error": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRs.Warnings": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanNotifRs.Warnings.Warning": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.Errors": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.Errors.Error": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.Warnings": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.Warnings.Warning": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.BookingRules": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.BookingRules.BookingRule": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.BookingRules.BookingRule.LengthsOfStay": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.BookingRules.BookingRule.LengthsOfStay.LengthOfStay": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.BookingRules.BookingRule.DowRestrictions": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.BookingRules.BookingRule.DowRestrictions.ArrivalDaysOfWeek": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.BookingRules.BookingRule.DowRestrictions.DepartureDaysOfWeek": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.BookingRules.BookingRule.RestrictionStatus": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Rates": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Rates.Rate": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Rates.Rate.BaseByGuestAmts": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Rates.Rate.BaseByGuestAmts.BaseByGuestAmt": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Rates.Rate.AdditionalGuestAmounts": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Rates.Rate.AdditionalGuestAmounts.AdditionalGuestAmount": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Rates.Rate.RateDescription": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Rates.Rate.RateDescription.ListItem": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Rates.Rate.MealsIncluded": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Supplements": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Supplements.Supplement": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Supplements.Supplement.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Supplements.Supplement.Description.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Supplements.Supplement.PrerequisiteInventory": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Offers": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Offers.Offer": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Offers.Offer.OfferRules": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Offers.Offer.OfferRules.OfferRule": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Offers.Offer.OfferRules.OfferRule.LengthsOfStay": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Offers.Offer.OfferRules.OfferRule.LengthsOfStay.LengthOfStay": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Offers.Offer.OfferRules.OfferRule.DowRestrictions": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Offers.Offer.OfferRules.OfferRule.DowRestrictions.ArrivalDaysOfWeek": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Offers.Offer.OfferRules.OfferRule.DowRestrictions.DepartureDaysOfWeek": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Offers.Offer.OfferRules.OfferRule.Occupancy": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Offers.Offer.Discount": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Offers.Offer.Guests": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Offers.Offer.Guests.Guest": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Description": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelRatePlanRs.RatePlans.RatePlan.Description.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.UniqueId": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.RoomTypes": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.RoomTypes.RoomType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.RatePlans": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.RatePlans.RatePlan": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.RatePlans.RatePlan.Commission": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.RatePlans.RatePlan.Commission.CommissionPayableAmount": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.RatePlans.RatePlan.MealsIncluded": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.RoomRates": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.RoomRates.RoomRate": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.RoomRates.RoomRate.Rates": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.RoomRates.RoomRate.Rates.Rate": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.RoomRates.RoomRate.Rates.Rate.Base": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.GuestCounts": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.GuestCounts.GuestCount": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.TimeSpan": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.TimeSpan.StartDateWindow": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.Guarantee": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.Guarantee.GuaranteesAccepted": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.Guarantee.GuaranteesAccepted.GuaranteeAccepted": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.Guarantee.GuaranteesAccepted.GuaranteeAccepted.PaymentCard": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.Guarantee.GuaranteesAccepted.GuaranteeAccepted.PaymentCard.CardNumber": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.Total": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.ServiceRphs": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.RoomStays.RoomStay.ServiceRphs.ServiceRph": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.Services": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.Services.Service": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.Services.Service.ServiceDetails": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.Services.Service.ServiceDetails.GuestCounts": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.Services.Service.ServiceDetails.GuestCounts.GuestCount": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.Services.Service.ServiceDetails.TimeSpan": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.Services.Service.ServiceDetails.Comments": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.Services.Service.ServiceDetails.Comments.Comment": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.Services.Service.ServiceDetails.Comments.Comment.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.Services.Service.ServiceDetails.Total": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.Services.Service.ServiceDetails.ServiceDescription": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.Services.Service.ServiceDetails.ServiceDescription.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGuests": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGuests.ResGuest": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGuests.ResGuest.Profiles": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer.PersonName": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer.Telephone": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer.Email": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer.Address": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer.Address.CountryName": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.Comments": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.Comments.Comment": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.Comments.Comment.ListItem": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.SpecialRequests": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.SpecialRequests.SpecialRequest": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.SpecialRequests.SpecialRequest.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.DepositPayments": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment.AcceptedPayments": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment.AcceptedPayments.AcceptedPayment": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment.AcceptedPayments.AcceptedPayment.PaymentCard": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment.AcceptedPayments.AcceptedPayment.PaymentCard.CardNumber": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment.AcceptedPayments.AcceptedPayment.BankAcct": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment.AcceptedPayments.AcceptedPayment.BankAcct.BankAcctNumber": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment.AcceptedPayments.AcceptedPayment.Voucher": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment.AmountPercent": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.CancelPenalties": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.CancelPenalties.CancelPenalty": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.CancelPenalties.CancelPenalty.PenaltyDescription": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.HotelReservationIds": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.HotelReservationIds.HotelReservationId": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.Profiles": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.Profiles.ProfileInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.Profiles.ProfileInfo.Profile": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.Profiles.ProfileInfo.Profile.CompanyInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.Profiles.ProfileInfo.Profile.CompanyInfo.CompanyName": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.Profiles.ProfileInfo.Profile.CompanyInfo.AddressInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.Profiles.ProfileInfo.Profile.CompanyInfo.AddressInfo.CountryName": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.Profiles.ProfileInfo.Profile.CompanyInfo.TelephoneInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGlobalInfo.BasicPropertyInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRs": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRs.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRs.Errors": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRs.Errors.Error": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRs.Warnings": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRs.Warnings.Warning": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRs.HotelReservations": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRs.HotelReservations.HotelReservation": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaHotelResNotifRs.HotelReservations.HotelReservation.UniqueId": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaNotifReportRq": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaNotifReportRq.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaNotifReportRq.Warnings": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaNotifReportRq.Warnings.Warning": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaNotifReportRq.NotifDetails": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaNotifReportRq.NotifDetails.HotelNotifReport": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaNotifReportRq.NotifDetails.HotelNotifReport.HotelReservations": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaNotifReportRq.NotifDetails.HotelNotifReport.HotelReservations.HotelReservation": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaNotifReportRq.NotifDetails.HotelNotifReport.HotelReservations.HotelReservation.UniqueId": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaNotifReportRs": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaNotifReportRs.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaNotifReportRs.Errors": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaNotifReportRs.Errors.Error": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaNotifReportRs.Warnings": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaNotifReportRs.Warnings.Warning": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaPingRs": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaPingRs.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaPingRs.Errors": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaPingRs.Errors.Error": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaPingRs.Warnings": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaPingRs.Warnings.Warning": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.Meta": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.Errors": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.Errors.Error": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.Warnings": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.Warnings.Warning": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.UniqueId": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.RoomTypes": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.RoomTypes.RoomType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.RatePlans": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.RatePlans.RatePlan": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.RatePlans.RatePlan.Commission": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.RatePlans.RatePlan.Commission.CommissionPayableAmount": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.RatePlans.RatePlan.MealsIncluded": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.RoomRates": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.RoomRates.RoomRate": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.RoomRates.RoomRate.Rates": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.RoomRates.RoomRate.Rates.Rate": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.RoomRates.RoomRate.Rates.Rate.Base": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.GuestCounts": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.GuestCounts.GuestCount": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.TimeSpan": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.TimeSpan.StartDateWindow": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.Guarantee": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.Guarantee.GuaranteesAccepted": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.Guarantee.GuaranteesAccepted.GuaranteeAccepted": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.Guarantee.GuaranteesAccepted.GuaranteeAccepted.PaymentCard": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.Guarantee.GuaranteesAccepted.GuaranteeAccepted.PaymentCard.CardNumber": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.Total": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.ServiceRphs": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.ServiceRphs.ServiceRph": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.Services": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.Services.Service": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.Services.Service.ServiceDetails": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.Services.Service.ServiceDetails.GuestCounts": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.Services.Service.ServiceDetails.GuestCounts.GuestCount": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.Services.Service.ServiceDetails.TimeSpan": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.Services.Service.ServiceDetails.Comments": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.Services.Service.ServiceDetails.Comments.Comment": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.Services.Service.ServiceDetails.Comments.Comment.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.Services.Service.ServiceDetails.Total": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.Services.Service.ServiceDetails.ServiceDescription": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.Services.Service.ServiceDetails.ServiceDescription.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGuests": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGuests.ResGuest": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGuests.ResGuest.Profiles": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer.PersonName": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer.Telephone": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer.Email": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer.Address": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer.Address.CountryName": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.Comments": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.Comments.Comment": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.Comments.Comment.ListItem": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.SpecialRequests": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.SpecialRequests.SpecialRequest": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.SpecialRequests.SpecialRequest.Text": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.DepositPayments": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment.AcceptedPayments": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment.AcceptedPayments.AcceptedPayment": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment.AcceptedPayments.AcceptedPayment.PaymentCard": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment.AcceptedPayments.AcceptedPayment.PaymentCard.CardNumber": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment.AcceptedPayments.AcceptedPayment.BankAcct": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment.AcceptedPayments.AcceptedPayment.BankAcct.BankAcctNumber": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment.AcceptedPayments.AcceptedPayment.Voucher": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.DepositPayments.GuaranteePayment.AmountPercent": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.CancelPenalties": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.CancelPenalties.CancelPenalty": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.CancelPenalties.CancelPenalty.PenaltyDescription": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.HotelReservationIds": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.HotelReservationIds.HotelReservationId": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.Profiles": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.Profiles.ProfileInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.Profiles.ProfileInfo.Profile": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.Profiles.ProfileInfo.Profile.CompanyInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.Profiles.ProfileInfo.Profile.CompanyInfo.CompanyName": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.Profiles.ProfileInfo.Profile.CompanyInfo.AddressInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.Profiles.ProfileInfo.Profile.CompanyInfo.AddressInfo.CountryName": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.Profiles.ProfileInfo.Profile.CompanyInfo.TelephoneInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.BasicPropertyInfo": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [1, 2, 3, 5, 6, 7, 9, 12, 13, 14, 17, 18, 21, 22, 23, 24, 25, 28, 29, 30, 31, 34, 35, 38, 39, 40, 41, 42, 43, 46, 47, 48, 51, 52, 55, 56, 59, 60, 63, 64, 65, 68, 69, 72, 73, 76, 77, 78, 79, 80, 83, 84, 85, 86, 87, 88, 89, 92, 93, 94, 95, 98, 99, 100, 101, 102, 105, 106, 107, 108, 111, 112, 115, 116, 117, 118, 119, 120, 123, 124, 125, 128, 129, 130, 131, 132, 135, 136, 137, 138, 141, 142, 143, 144, 146, 147, 154, 161, 169, 170, 171, 179, 180, 181, 190, 201, 202, 203, 204, 206, 207, 214, 221, 229, 230, 231, 239, 240, 241, 248, 257, 265, 266, 267, 275, 284, 285, 286, 297, 298, 299, 308, 318, 319, 320, 329, 340, 341, 342, 343, 345, 346, 354, 361, 370, 371, 372, 373, 375, 376, 383, 390, 398, 399, 400, 408, 409, 410, 419, 428, 438, 439, 440, 450, 451, 452, 455, 456, 459, 460, 461, 464, 465, 468, 469, 472, 473, 474, 475, 476, 479, 480, 483, 484, 487, 488, 491, 492, 493, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 508, 509, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 524, 525, 526, 527, 528, 529, 532, 533, 536, 537, 538, 541, 542, 543, 546, 547, 548, 551, 552, 553, 554, 555, 556, 557, 558, 561, 562, 563, 566, 567, 570, 571, 574, 575, 578, 579, 582, 583, 584, 587, 588, 590, 591, 592, 593, 594, 595, 596, 597, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 612, 613, 616, 617, 620, 621, 622, 625, 626, 627, 630, 631, 634, 635, 636, 637, 638, 639, 640, 643, 644, 647, 648, 649, 650, 651, 654, 655, 656, 657, 659, 660, 667, 674, 682, 683, 684, 692, 693, 694, 703, 712, 721, 730, 739, 748, 757, 766, 775, 776, 777, 786, 795, 804, 813, 822, 823, 824, 832, 833, 834, 842, 852, 853, 854, 862, 863, 864, 875, 876, 877, 886, 895, 904, 912, 913, 914, 924, 925, 926, 936, 945, 955, 956, 957, 964, 971, 980, 981, 982, 993, 994, 995, 1002, 1011, 1019, 1020, 1021, 1029, 1038, 1047, 1056, 1064, 1073, 1074, 1075, 1082, 1089, 1098, 1099, 1100, 1111, 1112, 1113, 1120, 1129, 1137, 1138, 1139, 1147, 1156, 1165, 1174, 1183, 1184, 1185, 1192, 1199, 1208, 1209, 1210, 1217, 1224, 1231, 1239, 1240, 1241, 1251, 1252, 1253, 1262, 1270, 1277, 1285, 1294, 1295, 1296, 1306, 1307, 1308, 1317, 1318, 1319, 1327, 1328, 1329, 1339, 1340, 1341, 1348, 1357, 1366, 1375, 1383, 1391, 1399, 1409, 1410, 1411, 1419, 1427, 1436, 1444, 1452, 1453, 1454, 1465, 1466, 1467, 1476, 1477, 1478, 1488, 1489, 1490, 1499, 1508, 1518, 1519, 1520, 1528, 1529, 1530, 1541, 1542, 1543, 1550, 1557, 1566, 1567, 1568, 1579, 1580, 1581, 1588, 1597, 1606, 1607, 1608, 1616, 1626, 1627, 1628, 1635, 1642, 1651, 1652, 1653, 1664, 1665, 1666, 1675, 1684, 1693, 1702, 1711, 1720, 1730, 1731, 1732, 1740, 1741, 1742, 1750, 1751, 1752, 1763, 1764, 1765, 1772, 1779, 1788, 1789, 1790, 1798, 1799, 1800, 1807, 1816, 1825, 1834, 1835, 1836, 1847, 1848, 1849, 1856, 1863, 1872, 1873, 1874, 1882, 1883, 1884, 1891, 1899, 1908, 1916, 1925, 1934, 1935, 1936, 1947, 1948, 1949, 1956, 1963, 1972, 1973, 1974, 1982, 1983, 1984, 1991, 2000, 2009, 2017, 2024, 2033, 2041, 2042, 2043, 2054, 2055, 2056, 2063, 2070, 2079, 2080, 2081, 2089, 2090, 2091, 2098, 2107, 2117, 2118, 2119, 2130, 2131, 2132, 2141, 2150, 2160, 2161, 2162, 2171, 2178, 2186, 2187, 2188, 2197, 2198, 2199, 2208, 2209, 2210, 2219, 2220, 2221, 2229, 2238, 2239, 2240, 2250, 2251, 2252, 2260, 2267, 2276, 2277, 2278, 2287, 2288, 2289, 2301, 2302, 2303, 2310, 2318, 2327, 2328, 2329, 2337, 2338, 2339, 2350, 2351, 2352, 2361, 2369, 2377, 2386, 2387, 2388, 2396, 2397, 2398, 2407, 2416, 2425, 2434, 2442, 2450, 2451, 2452, 2463, 2464, 2465, 2474, 2483, 2492, 2501, 2510, 2519, 2520, 2521, 2530, 2531, 2532, 2541, 2542, 2543, 2554, 2555, 2556, 2564, 2573, 2574, 2575, 2586, 2587, 2588, 2595, 2604, 2605, 2606, 2617, 2618, 2619, 2625, 2635, 2636, 2637, 2638, 2640, 2641, 2648, 2655, 2662, 2669, 2677, 2678, 2679, 2688, 2689, 2690, 2697, 2705, 2712, 2721, 2722, 2723, 2732, 2733, 2734, 2742, 2751, 2758, 2768, 2769, 2770, 2771, 2773, 2774, 2781, 2788, 2795, 2804, 2811, 2819, 2820, 2821, 2830, 2831, 2832, 2839, 2847, 2854, 2863, 2864, 2865, 2874, 2875, 2876, 2884, 2893, 2900, 2909, 2910, 2911, 2919, 2920, 2921, 2930, 2939, 2948, 2957, 2966, 2975, 2984, 2993, 3002, 3003, 3004, 3013, 3022, 3031, 3040, 3049, 3050, 3051, 3059, 3060, 3061, 3069, 3079, 3080, 3081, 3089, 3090, 3091, 3102, 3103, 3104, 3113, 3122, 3131, 3139, 3140, 3141, 3151, 3152, 3153, 3163, 3172, 3182, 3183, 3184, 3191, 3198, 3207, 3208, 3209, 3220, 3221, 3222, 3229, 3238, 3246, 3247, 3248, 3256, 3265, 3274, 3283, 3291, 3300, 3301, 3302, 3309, 3316, 3325, 3326, 3327, 3338, 3339, 3340, 3347, 3356, 3364, 3365, 3366, 3374, 3383, 3392, 3401, 3410, 3411, 3412, 3419, 3426, 3435, 3436, 3437, 3444, 3451, 3458, 3466, 3467, 3468, 3478, 3479, 3480, 3489, 3497, 3504, 3512, 3521, 3522, 3523, 3533, 3534, 3535, 3544, 3545, 3546, 3554, 3555, 3556, 3566, 3567, 3568, 3575, 3584, 3593, 3602, 3610, 3618, 3626, 3636, 3637, 3638, 3646, 3654, 3663, 3671, 3679, 3680, 3681, 3692, 3693, 3694, 3703, 3704, 3705, 3715, 3716, 3717, 3726, 3735, 3745, 3746, 3747, 3755, 3756, 3757, 3768, 3769, 3770, 3777, 3784, 3793, 3794, 3795, 3806, 3807, 3808, 3815, 3824, 3833, 3834, 3835, 3843, 3853, 3854, 3855, 3862, 3869, 3878, 3879, 3880, 3891, 3892, 3893, 3902, 3911, 3920, 3929, 3938, 3947, 3957, 3958, 3959, 3967, 3968, 3969, 3977, 3978, 3979, 3990, 3991, 3992, 3999, 4006, 4015, 4016, 4017, 4025, 4026, 4027, 4034, 4043, 4052, 4061, 4062, 4063, 4074, 4075, 4076, 4083, 4090, 4099, 4100, 4101, 4109, 4110, 4111, 4118, 4126, 4135, 4143, 4152, 4161, 4162, 4163, 4174, 4175, 4176, 4183, 4190, 4199, 4200, 4201, 4209, 4210, 4211, 4218, 4227, 4236, 4244, 4251, 4260, 4268, 4269, 4270, 4281, 4282, 4283, 4290, 4297, 4306, 4307, 4308, 4316, 4317, 4318, 4325, 4334, 4344, 4345, 4346, 4357, 4358, 4359, 4368, 4377, 4387, 4388, 4389, 4398, 4405, 4413, 4414, 4415, 4424, 4425, 4426, 4435, 4436, 4437, 4446, 4447, 4448, 4456, 4465, 4466, 4467, 4477, 4478, 4479, 4487, 4494, 4503, 4504, 4505, 4514, 4515, 4516, 4528, 4529, 4530, 4537, 4545, 4554, 4555, 4556, 4564, 4565, 4566, 4577, 4578, 4579, 4588, 4596, 4604, 4613, 4614, 4615, 4623, 4624, 4625, 4634, 4643, 4652, 4661, 4669, 4677, 4678, 4679, 4690, 4691, 4692, 4701, 4710, 4719, 4728, 4737, 4746, 4747, 4748, 4757, 4758, 4759, 4768, 4769, 4770, 4781, 4782, 4783, 4791, 4800, 4801, 4802, 4813, 4814, 4815, 4822, 4831, 4832, 4833, 4844, 4845, 4846, 4852, 4862, 4863, 4864, 4865, 4867, 4868, 4875, 4882, 4890, 4891, 4892, 4899, 4906, 4914, 4915, 4916, 4924, 4933, 4943, 4944, 4945, 4954, 4964, 4965, 4966, 4974, 4982, 4991, 5000, 5009, 5010, 5011, 5023, 5024, 5025, 5032, 5042, 5043, 5044, 5045, 5047, 5048, 5055, 5062, 5069, 5076, 5084, 5085, 5086, 5095, 5096, 5097, 5104, 5112, 5119, 5128, 5129, 5130, 5139, 5140, 5141, 5149, 5158, 5165, 5175, 5176, 5177, 5178, 5180, 5181, 5188, 5196, 5197, 5198, 5208, 5209, 5210, 5217, 5225, 5226, 5227, 5235, 5236, 5237, 5244, 5253, 5263, 5264, 5265, 5274, 5283, 5291, 5292, 5293, 5302, 5311, 5320, 5329, 5337, 5345, 5355, 5356, 5357, 5368, 5369, 5370, 5379, 5388, 5397, 5407, 5408, 5409, 5418, 5428, 5429, 5430, 5437, 5445, 5446, 5447, 5457, 5458, 5459, 5467, 5476, 5477, 5478, 5490, 5491, 5492, 5501, 5510, 5517, 5525, 5526, 5527, 5535, 5536, 5537, 5546, 5557, 5558, 5559, 5568, 5569, 5570, 5577, 5586, 5587, 5588, 5599, 5600, 5601, 5610, 5618, 5626, 5627, 5628, 5635, 5645, 5646, 5647, 5648, 5650, 5651, 5658, 5665, 5672, 5679, 5687, 5688, 5689, 5698, 5699, 5700, 5707, 5715, 5722, 5731, 5732, 5733, 5742, 5743, 5744, 5752, 5761, 5768, 5778, 5779, 5780, 5781, 5783, 5784, 5791, 5798, 5805, 5813, 5814, 5815, 5822, 5829, 5837, 5838, 5839, 5847, 5856, 5866, 5867, 5868, 5877, 5884, 5893, 5902, 5912, 5920, 5928, 5935, 5944, 5953, 5960, 5969, 5978, 5987, 5988, 5989, 6000, 6001, 6002, 6011, 6020, 6029, 6036, 6045, 6053, 6062, 6063, 6064, 6075, 6076, 6077, 6086, 6093, 6103, 6104, 6105, 6114, 6124, 6125, 6126, 6134, 6142, 6150, 6158, 6166, 6174, 6183, 6184, 6185, 6193, 6201, 6209, 6217, 6225, 6233, 6242, 6243, 6244, 6251, 6259, 6260, 6261, 6272, 6273, 6274, 6283, 6292, 6301, 6310, 6318, 6326, 6334, 6341, 6349, 6357, 6365, 6373, 6381, 6389, 6397, 6405, 6413, 6423, 6424, 6425, 6436, 6437, 6438, 6446, 6455, 6464, 6471, 6480, 6481, 6482, 6493, 6494, 6495, 6504, 6512, 6520, 6529, 6530, 6531, 6541, 6549, 6550, 6551, 6558, 6566, 6575, 6576, 6577, 6585, 6593, 6601, 6608, 6616, 6617, 6618, 6629, 6630, 6631, 6640, 6650, 6657, 6664, 6673, 6680, 6689, 6697, 6705, 6714, 6715, 6716, 6724, 6732, 6741, 6749, 6757, 6758, 6759, 6766, 6773, 6782, 6783, 6784, 6793, 6801, 6802, 6803, 6815, 6816, 6817, 6826, 6835, 6845, 6846, 6847, 6857, 6858, 6859, 6868, 6877, 6887, 6895, 6904, 6905, 6906, 6917, 6918, 6919, 6928, 6935, 6943, 6944, 6945, 6954, 6964, 6965, 6966, 6974, 6982, 6990, 6998, 7006, 7014, 7023, 7024, 7025, 7033, 7041, 7049, 7057, 7065, 7073, 7082, 7083, 7084, 7091, 7099, 7107, 7115, 7124, 7125, 7126, 7133, 7141, 7149, 7158, 7159, 7160, 7168, 7169, 7170, 7178, 7186, 7194, 7203, 7212, 7213, 7214, 7222, 7230, 7239, 7247, 7255, 7256, 7257, 7264, 7271, 7281, 7282, 7283, 7284, 7286, 7287, 7294, 7301, 7308, 7315, 7323, 7324, 7325, 7334, 7335, 7336, 7343, 7351, 7358, 7367, 7368, 7369, 7378, 7379, 7380, 7388, 7397, 7404, 7414, 7415, 7416, 7417, 7419, 7420, 7427, 7434, 7441, 7448, 7455, 7463, 7464, 7465, 7474, 7475, 7476, 7483, 7491, 7498, 7507, 7508, 7509, 7518, 7519, 7520, 7528, 7537, 7544, 7553, 7554, 7555, 7563, 7572, 7582, 7583, 7584, 7593, 7600, 7609, 7616, 7626, 7634, 7642, 7649, 7658, 7667, 7674, 7683, 7692, 7701, 7702, 7703, 7714, 7715, 7716, 7725, 7734, 7743, 7750, 7759, 7767, 7776, 7777, 7778, 7789, 7790, 7791, 7800, 7807, 7817, 7818, 7819, 7828, 7838, 7839, 7840, 7848, 7856, 7864, 7872, 7880, 7888, 7897, 7898, 7899, 7907, 7915, 7923, 7931, 7939, 7947, 7956, 7957, 7958, 7965, 7973, 7974, 7975, 7984, 7985, 7986, 7995, 8004, 8013, 8022, 8030, 8038, 8046, 8053, 8061, 8069, 8077, 8085, 8093, 8101, 8109, 8117, 8125, 8135, 8136, 8137, 8148, 8149, 8150, 8158, 8167, 8176, 8183, 8192, 8193, 8194, 8205, 8206, 8207, 8216, 8224, 8232, 8241, 8242, 8243, 8253, 8261, 8262, 8263, 8270, 8278, 8287, 8288, 8289, 8297, 8305, 8313, 8320, 8328, 8329, 8330, 8341, 8342, 8343, 8352, 8362, 8369, 8376, 8385, 8392, 8401, 8409, 8417, 8426, 8427, 8428, 8436, 8444, 8453, 8461, 8469, 8470, 8471, 8478, 8485, 8494, 8495, 8496, 8505, 8513, 8514, 8515, 8527, 8528, 8529, 8538, 8547, 8557, 8558, 8559, 8569, 8570, 8571, 8580, 8589, 8599, 8607, 8616, 8617, 8618, 8629, 8630, 8631, 8640, 8647, 8655, 8656, 8657, 8666, 8676, 8677, 8678, 8686, 8694, 8702, 8710, 8718, 8726, 8735, 8736, 8737, 8745, 8753, 8761, 8769, 8777, 8785, 8794, 8795, 8796, 8803, 8811, 8819, 8827, 8836, 8837, 8838, 8845, 8853, 8861, 8870, 8871, 8872, 8880, 8881, 8882, 8890, 8898, 8906, 8915, 8924, 8925, 8926, 8934, 8942, 8951, 8959, 8967, 8968, 8969, 8976, 8983, 8993, 8994, 8995, 8996, 8998, 8999, 9006, 9013, 9021, 9022, 9023, 9033, 9034, 9035, 9042, 9051, 9060, 9069, 9078, 9086, 9094, 9101, 9110, 9111, 9112, 9119, 9129, 9130, 9131, 9142, 9143, 9144, 9153, 9162, 9171, 9180, 9187, 9196, 9205, 9214, 9224, 9225, 9226, 9234, 9235, 9236, 9245, 9253, 9261, 9262, 9263, 9271, 9272, 9273, 9282, 9291, 9301, 9302, 9303, 9312, 9321, 9322, 9323, 9332, 9342, 9343, 9344, 9353, 9361, 9362, 9363, 9371, 9372, 9373, 9380, 9389, 9399, 9400, 9401, 9412, 9413, 9414, 9424, 9432, 9440, 9448, 9455, 9464, 9465, 9466, 9475, 9485, 9486, 9487, 9498, 9499, 9500, 9508, 9517, 9518, 9519, 9528, 9536, 9544, 9553, 9554, 9555, 9563, 9572, 9573, 9574, 9582, 9583, 9584, 9592, 9593, 9594, 9602, 9603, 9604, 9613, 9620, 9628, 9637, 9638, 9639, 9647, 9655, 9664, 9665, 9666, 9675, 9685, 9686, 9687, 9698, 9699, 9700, 9709, 9710, 9711, 9722, 9723, 9724, 9731, 9740, 9747, 9754, 9763, 9771, 9778, 9785, 9794, 9795, 9796, 9805, 9814, 9823, 9830, 9840, 9841, 9842, 9854, 9855, 9856, 9864, 9873, 9874, 9875, 9883, 9892, 9893, 9894, 9902, 9903, 9904, 9912, 9913, 9914, 9921, 9929, 9930, 9931, 9940, 9950, 9951, 9952, 9960, 9961, 9962, 9969, 9977, 9978, 9979, 9987, 9988, 9989, 9997, 9998, 9999, 10007, 10008, 10009, 10017, 10018, 10019, 10027, 10028, 10029, 10036, 10045, 10054, 10063, 10071, 10079, 10088, 10089, 10090, 10099, 10108, 10117, 10127, 10128, 10129, 10137, 10146, 10147, 10148, 10155, 10164, 10165, 10166, 10175, 10184, 10193, 10202, 10211, 10212, 10213, 10222, 10223, 10224, 10233, 10242, 10251, 10260, 10269, 10278, 10286, 10287, 10288, 10300, 10301, 10302, 10311, 10319, 10327, 10328, 10329, 10336, 10344, 10353, 10354, 10355, 10366, 10367, 10368, 10377, 10386, 10394, 10395, 10396, 10402, 10410, 10411, 10412, 10423, 10424, 10425, 10432, 10441, 10448, 10456, 10457, 10458, 10466, 10467, 10468, 10477, 10486, 10495, 10502, 10509, 10517, 10518, 10519, 10528, 10537, 10545, 10554, 10555, 10556, 10564, 10572, 10581, 10582, 10583, 10592, 10600, 10601, 10602, 10610, 10619, 10620, 10621, 10629, 10639, 10640, 10641, 10650, 10660, 10661, 10662, 10670, 10671, 10672, 10680, 10681, 10682, 10691, 10692, 10693, 10704, 10705, 10706, 10714, 10723, 10732, 10742, 10743, 10744, 10752, 10753, 10754, 10762, 10763, 10764, 10771, 10779, 10780, 10781, 10788, 10797, 10806, 10815, 10816, 10817, 10824, 10832, 10841, 10842, 10843, 10852, 10861, 10870, 10878, 10879, 10880, 10889, 10890, 10891, 10899, 10908, 10909, 10910, 10919, 10930, 10931, 10932, 10933, 10935, 10936, 10943, 10950, 10957, 10964, 10971, 10979, 10980, 10981, 10990, 10991, 10992, 10999, 11007, 11014, 11023, 11024, 11025, 11034, 11035, 11036, 11044, 11052, 11061, 11068, 11077, 11078, 11079, 11090, 11091, 11092, 11100, 11101, 11102, 11109, 11120, 11121, 11122, 11123, 11125, 11126, 11133, 11140, 11147, 11154, 11162, 11163, 11164, 11173, 11174, 11175, 11183, 11191, 11200, 11207, 11216, 11217, 11218, 11226, 11227, 11228, 11236, 11237, 11238, 11249, 11250, 11251, 11259, 11260, 11261, 11268, 11279, 11280, 11281, 11282, 11284, 11285, 11292, 11299, 11306, 11313, 11321, 11322, 11323, 11332, 11333, 11334, 11341, 11349, 11356, 11365, 11366, 11367, 11376, 11377, 11378, 11386, 11395, 11402, 11412, 11413, 11414, 11415, 11417, 11418, 11425, 11432, 11439, 11447, 11454, 11462, 11463, 11464, 11473, 11474, 11475, 11482, 11490, 11497, 11506, 11507, 11508, 11517, 11518, 11519, 11527, 11534, 11544, 11545, 11546, 11547, 11549, 11550, 11557, 11564, 11571, 11578, 11585, 11593, 11594, 11595, 11604, 11605, 11606, 11613, 11621, 11628, 11637, 11638, 11639, 11648, 11649, 11650, 11658, 11666, 11675, 11682, 11691, 11692, 11693, 11703, 11704, 11705, 11714, 11723, 11732, 11741, 11750, 11758, 11766, 11773, 11782, 11783, 11784, 11791, 11801, 11802, 11803, 11814, 11815, 11816, 11825, 11834, 11843, 11852, 11859, 11868, 11877, 11886, 11896, 11897, 11898, 11906, 11907, 11908, 11917, 11925, 11933, 11934, 11935, 11943, 11944, 11945, 11954, 11963, 11973, 11974, 11975, 11984, 11993, 11994, 11995, 12004, 12014, 12015, 12016, 12025, 12033, 12034, 12035, 12043, 12044, 12045, 12052, 12061, 12071, 12072, 12073, 12084, 12085, 12086, 12096, 12104, 12112, 12120, 12127, 12136, 12137, 12138, 12147, 12157, 12158, 12159, 12170, 12171, 12172, 12180, 12189, 12190, 12191, 12200, 12208, 12216, 12225, 12226, 12227, 12235, 12244, 12245, 12246, 12254, 12255, 12256, 12264, 12265, 12266, 12274, 12275, 12276, 12285, 12292, 12300, 12309, 12310, 12311, 12319, 12327, 12336, 12337, 12338, 12347, 12357, 12358, 12359, 12370, 12371, 12372, 12381, 12382, 12383, 12394, 12395, 12396, 12403, 12412, 12419, 12426, 12435, 12443, 12450, 12457, 12466, 12467, 12468, 12477, 12486, 12495, 12502, 12512, 12513, 12514, 12526, 12527, 12528, 12536, 12545, 12546, 12547, 12555, 12564, 12565, 12566, 12574, 12575, 12576, 12584, 12585, 12586, 12593, 12601, 12602, 12603, 12612, 12622, 12623, 12624, 12632, 12633, 12634, 12641, 12649, 12650, 12651, 12659, 12660, 12661, 12669, 12670, 12671, 12679, 12680, 12681, 12689, 12690, 12691, 12699, 12700, 12701, 12708, 12717, 12726, 12735, 12743, 12751, 12760, 12761, 12762, 12771, 12780, 12789, 12799, 12800, 12801, 12809, 12818, 12819, 12820, 12827, 12836, 12837, 12838, 12847, 12856, 12865, 12874, 12883, 12884, 12885, 12894, 12895, 12896, 12905, 12914, 12923, 12932, 12941, 12950, 12958, 12959, 12960, 12972, 12973, 12974, 12983, 12991, 12999, 13000, 13001, 13008, 13016, 13025, 13026, 13027, 13038, 13039, 13040, 13049, 13058, 13066, 13067, 13068, 13074, 13082, 13083, 13084, 13095, 13096, 13097, 13104, 13113, 13120, 13128, 13129, 13130, 13138, 13139, 13140, 13149, 13158, 13167, 13174, 13181, 13189, 13190, 13191, 13200, 13209, 13217, 13226, 13227, 13228, 13236, 13244, 13253, 13254, 13255, 13264, 13272, 13273, 13274, 13282, 13291, 13292, 13293, 13301, 13311, 13312, 13313, 13322, 13332, 13333, 13334, 13342, 13343, 13344, 13352, 13353, 13354, 13363, 13364, 13365, 13376, 13377, 13378, 13386, 13395, 13404, 13414, 13415, 13416, 13424, 13425, 13426, 13434, 13435, 13436, 13443, 13451, 13452, 13453, 13460, 13469, 13478, 13487, 13488, 13489, 13496, 13504, 13513, 13514, 13515, 13524, 13533, 13542, 13550, 13551, 13552, 13561, 13562, 13563, 13571, 13580, 13581, 13582, 13591], "summary": {"covered_lines": 2756, "num_statements": 2756, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "src/alpine_bits_python/logging_config.py": {"executed_lines": [1, 7, 8, 9, 12, 71, 87], "summary": {"covered_lines": 6, "num_statements": 30, "percent_covered": 20.0, "percent_covered_display": "20", "missing_lines": 24, "excluded_lines": 0}, "missing_lines": [24, 25, 27, 28, 29, 32, 35, 41, 42, 45, 48, 49, 50, 51, 54, 55, 58, 59, 61, 62, 63, 64, 66, 68], "excluded_lines": [], "functions": {"setup_logging": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 24, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 24, "excluded_lines": 0}, "missing_lines": [24, 25, 27, 28, 29, 32, 35, 41, 42, 45, 48, 49, 50, 51, 54, 55, 58, 59, 61, 62, 63, 64, 66, 68], "excluded_lines": []}, "get_logger": {"executed_lines": [87], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [1, 7, 8, 9, 12, 71], "summary": {"covered_lines": 5, "num_statements": 5, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"": {"executed_lines": [1, 7, 8, 9, 12, 71, 87], "summary": {"covered_lines": 6, "num_statements": 30, "percent_covered": 20.0, "percent_covered_display": "20", "missing_lines": 24, "excluded_lines": 0}, "missing_lines": [24, 25, 27, 28, 29, 32, 35, 41, 42, 45, 48, 49, 50, 51, 54, 55, 58, 59, 61, 62, 63, 64, 66, 68], "excluded_lines": []}}}, "src/alpine_bits_python/rate_limit.py": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 46, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 46, "excluded_lines": 0}, "missing_lines": [1, 2, 4, 5, 6, 7, 8, 10, 13, 14, 15, 18, 21, 24, 25, 27, 29, 30, 31, 34, 38, 40, 41, 43, 44, 47, 48, 49, 52, 55, 56, 59, 64, 65, 66, 68, 71, 75, 76, 80, 86, 88, 93, 96, 97, 99], "excluded_lines": [], "functions": {"get_remote_address_with_forwarded": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 7, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 7, "excluded_lines": 0}, "missing_lines": [24, 25, 27, 29, 30, 31, 34], "excluded_lines": []}, "get_api_key_identifier": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 5, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 5, "excluded_lines": 0}, "missing_lines": [64, 65, 66, 68, 71], "excluded_lines": []}, "api_key_rate_limit_key": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [76], "excluded_lines": []}, "custom_rate_limit_handler": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 5, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 5, "excluded_lines": 0}, "missing_lines": [88, 93, 96, 97, 99], "excluded_lines": []}, "": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 28, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 28, "excluded_lines": 0}, "missing_lines": [1, 2, 4, 5, 6, 7, 8, 10, 13, 14, 15, 18, 21, 38, 40, 41, 43, 44, 47, 48, 49, 52, 55, 56, 59, 75, 80, 86], "excluded_lines": []}}, "classes": {"": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 46, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 46, "excluded_lines": 0}, "missing_lines": [1, 2, 4, 5, 6, 7, 8, 10, 13, 14, 15, 18, 21, 24, 25, 27, 29, 30, 31, 34, 38, 40, 41, 43, 44, 47, 48, 49, 52, 55, 56, 59, 64, 65, 66, 68, 71, 75, 76, 80, 86, 88, 93, 96, 97, 99], "excluded_lines": []}}}, "src/alpine_bits_python/run_api.py": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 7, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 7, "excluded_lines": 0}, "missing_lines": [4, 6, 8, 9, 10, 11, 13], "excluded_lines": [], "functions": {"": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 7, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 7, "excluded_lines": 0}, "missing_lines": [4, 6, 8, 9, 10, 11, 13], "excluded_lines": []}}, "classes": {"": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 7, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 7, "excluded_lines": 0}, "missing_lines": [4, 6, 8, 9, 10, 11, 13], "excluded_lines": []}}}, "src/alpine_bits_python/schemas.py": {"executed_lines": [1, 12, 13, 14, 16, 20, 21, 22, 23, 26, 27, 29, 30, 32, 33, 34, 39, 40, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 62, 63, 69, 72, 73, 75, 76, 78, 83, 84, 86, 89, 90, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 105, 106, 107, 108, 110, 111, 112, 114, 116, 118, 119, 120, 122, 124, 125, 126, 128, 130, 133, 134, 136, 137, 138, 139, 141, 144, 145, 151, 152, 154, 156, 158, 161, 162, 163, 165, 168, 169, 171, 172, 173, 175, 176, 177, 181, 184, 185, 187, 188, 189, 191, 192, 193, 203, 206, 207, 209, 211, 212, 213, 215, 217, 219, 223, 224, 226, 229], "summary": {"covered_lines": 119, "num_statements": 140, "percent_covered": 85.0, "percent_covered_display": "85", "missing_lines": 21, "excluded_lines": 0}, "missing_lines": [36, 79, 85, 115, 159, 179, 197, 198, 199, 200, 201, 216, 227, 236, 239, 240, 241, 244, 251, 252, 254], "excluded_lines": [], "functions": {"PhoneNumber.clean_phone_number": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [36], "excluded_lines": []}, "ReservationData.ensure_md5": {"executed_lines": [69, 72, 73], "summary": {"covered_lines": 3, "num_statements": 3, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ReservationData.validate_children_ages": {"executed_lines": [78, 83, 84, 86], "summary": {"covered_lines": 4, "num_statements": 6, "percent_covered": 66.66666666666667, "percent_covered_display": "67", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [79, 85], "excluded_lines": []}, "CustomerData.name_must_not_be_empty": {"executed_lines": [114, 116], "summary": {"covered_lines": 2, "num_statements": 3, "percent_covered": 66.66666666666667, "percent_covered_display": "67", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [115], "excluded_lines": []}, "CustomerData.normalize_country_code": {"executed_lines": [122], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "CustomerData.normalize_language": {"executed_lines": [128], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "HotelReservationIdData.trim_and_truncate": {"executed_lines": [151, 152, 154, 156, 158, 161, 162, 163], "summary": {"covered_lines": 8, "num_statements": 9, "percent_covered": 88.88888888888889, "percent_covered_display": "89", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [159], "excluded_lines": []}, "CommentListItemData.normalize_language": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [179], "excluded_lines": []}, "CommentData.validate_list_items": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 5, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 5, "excluded_lines": 0}, "missing_lines": [197, 198, 199, 200, 201], "excluded_lines": []}, "CommentsData.validate_comment_count": {"executed_lines": [215, 217], "summary": {"covered_lines": 2, "num_statements": 3, "percent_covered": 66.66666666666667, "percent_covered_display": "67", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [216], "excluded_lines": []}, "ReservationService.__init__": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [227], "excluded_lines": []}, "ReservationService.create_reservation": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 8, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 8, "excluded_lines": 0}, "missing_lines": [236, 239, 240, 241, 244, 251, 252, 254], "excluded_lines": []}, "": {"executed_lines": [1, 12, 13, 14, 16, 20, 21, 22, 23, 26, 27, 29, 30, 32, 33, 34, 39, 40, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 62, 63, 75, 76, 89, 90, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 105, 106, 107, 108, 110, 111, 112, 118, 119, 120, 124, 125, 126, 130, 133, 134, 136, 137, 138, 139, 141, 144, 145, 165, 168, 169, 171, 172, 173, 175, 176, 177, 181, 184, 185, 187, 188, 189, 191, 192, 193, 203, 206, 207, 209, 211, 212, 213, 219, 223, 224, 226, 229], "summary": {"covered_lines": 98, "num_statements": 98, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"PhoneTechType": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "PhoneNumber": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [36], "excluded_lines": []}, "ReservationData": {"executed_lines": [69, 72, 73, 78, 83, 84, 86], "summary": {"covered_lines": 7, "num_statements": 9, "percent_covered": 77.77777777777777, "percent_covered_display": "78", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [79, 85], "excluded_lines": []}, "CustomerData": {"executed_lines": [114, 116, 122, 128], "summary": {"covered_lines": 4, "num_statements": 5, "percent_covered": 80.0, "percent_covered_display": "80", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [115], "excluded_lines": []}, "HotelReservationIdData": {"executed_lines": [151, 152, 154, 156, 158, 161, 162, 163], "summary": {"covered_lines": 8, "num_statements": 9, "percent_covered": 88.88888888888889, "percent_covered_display": "89", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [159], "excluded_lines": []}, "CommentListItemData": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [179], "excluded_lines": []}, "CommentData": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 5, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 5, "excluded_lines": 0}, "missing_lines": [197, 198, 199, 200, 201], "excluded_lines": []}, "CommentsData": {"executed_lines": [215, 217], "summary": {"covered_lines": 2, "num_statements": 3, "percent_covered": 66.66666666666667, "percent_covered_display": "67", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [216], "excluded_lines": []}, "ReservationService": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 9, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 9, "excluded_lines": 0}, "missing_lines": [227, 236, 239, 240, 241, 244, 251, 252, 254], "excluded_lines": []}, "": {"executed_lines": [1, 12, 13, 14, 16, 20, 21, 22, 23, 26, 27, 29, 30, 32, 33, 34, 39, 40, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 62, 63, 75, 76, 89, 90, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 105, 106, 107, 108, 110, 111, 112, 118, 119, 120, 124, 125, 126, 130, 133, 134, 136, 137, 138, 139, 141, 144, 145, 165, 168, 169, 171, 172, 173, 175, 176, 177, 181, 184, 185, 187, 188, 189, 191, 192, 193, 203, 206, 207, 209, 211, 212, 213, 219, 223, 224, 226, 229], "summary": {"covered_lines": 98, "num_statements": 98, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "src/alpine_bits_python/util/__init__.py": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": [], "functions": {"": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "src/alpine_bits_python/util/__main__.py": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [3, 5, 6], "excluded_lines": [], "functions": {"": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [3, 5, 6], "excluded_lines": []}}, "classes": {"": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [3, 5, 6], "excluded_lines": []}}}, "src/alpine_bits_python/util/handshake_util.py": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 15, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 15, "excluded_lines": 0}, "missing_lines": [1, 3, 6, 9, 13, 14, 20, 22, 25, 31, 32, 33, 35, 38, 39], "excluded_lines": [], "functions": {"main": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 10, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 10, "excluded_lines": 0}, "missing_lines": [9, 13, 14, 20, 22, 25, 31, 32, 33, 35], "excluded_lines": []}, "": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 5, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 5, "excluded_lines": 0}, "missing_lines": [1, 3, 6, 38, 39], "excluded_lines": []}}, "classes": {"": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 15, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 15, "excluded_lines": 0}, "missing_lines": [1, 3, 6, 9, 13, 14, 20, 22, 25, 31, 32, 33, 35, 38, 39], "excluded_lines": []}}}}, "totals": {"covered_lines": 3512, "num_statements": 4243, "percent_covered": 82.77162385104879, "percent_covered_display": "83", "missing_lines": 731, "excluded_lines": 0}} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 35b64a2..9552102 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,111 +40,115 @@ testpaths = ["tests"] pythonpath = ["src"] [tool.ruff] -src = ["src", "test"] +src = ["src", "tests"] [tool.ruff.lint] select = [ - "A001", # Variable {name} is shadowing a Python builtin + "A001", # Variable {name} is shadowing a Python builtin "ASYNC210", # Async functions should not call blocking HTTP methods "ASYNC220", # Async functions should not create subprocesses with blocking methods "ASYNC221", # Async functions should not run processes with blocking methods "ASYNC222", # Async functions should not wait on processes with blocking methods "ASYNC230", # Async functions should not open files with blocking methods like open "ASYNC251", # Async functions should not call time.sleep - "B002", # Python does not support the unary prefix increment - "B005", # Using .strip() with multi-character strings is misleading - "B007", # Loop control variable {name} not used within loop body - "B014", # Exception handler with duplicate exception - "B015", # Pointless comparison. Did you mean to assign a value? Otherwise, prepend assert or remove it. - "B017", # pytest.raises(BaseException) should be considered evil - "B018", # Found useless attribute access. Either assign it to a variable or remove it. - "B023", # Function definition does not bind loop variable {name} - "B024", # `{name}` is an abstract base class, but it has no abstract methods or properties - "B026", # Star-arg unpacking after a keyword argument is strongly discouraged - "B032", # Possible unintentional type annotation (using :). Did you mean to assign (using =)? - "B035", # Dictionary comprehension uses static key - "B904", # Use raise from to specify exception cause - "B905", # zip() without an explicit strict= parameter + "B002", # Python does not support the unary prefix increment + "B005", # Using .strip() with multi-character strings is misleading + "B007", # Loop control variable {name} not used within loop body + "B014", # Exception handler with duplicate exception + "B015", # Pointless comparison. Did you mean to assign a value? Otherwise, prepend assert or remove it. + "B017", # pytest.raises(BaseException) should be considered evil + "B018", # Found useless attribute access. Either assign it to a variable or remove it. + "B023", # Function definition does not bind loop variable {name} + "B024", # `{name}` is an abstract base class, but it has no abstract methods or properties + "B026", # Star-arg unpacking after a keyword argument is strongly discouraged + "B032", # Possible unintentional type annotation (using :). Did you mean to assign (using =)? + "B035", # Dictionary comprehension uses static key + "B904", # Use raise from to specify exception cause + "B905", # zip() without an explicit strict= parameter "BLE", - "C", # complexity - "COM818", # Trailing comma on bare tuple prohibited - "D", # docstrings - "DTZ003", # Use datetime.now(tz=) instead of datetime.utcnow() - "DTZ004", # Use datetime.fromtimestamp(ts, tz=) instead of datetime.utcfromtimestamp(ts) - "E", # pycodestyle - "F", # pyflakes/autoflake - "F541", # f-string without any placeholders - "FLY", # flynt - "FURB", # refurb - "G", # flake8-logging-format - "I", # isort - "INP", # flake8-no-pep420 - "ISC", # flake8-implicit-str-concat - "ICN001", # import concentions; {name} should be imported as {asname} - "LOG", # flake8-logging - "N804", # First argument of a class method should be named cls - "N805", # First argument of a method should be named self - "N815", # Variable {name} in class scope should not be mixedCase - "PERF", # Perflint - "PGH", # pygrep-hooks - "PIE", # flake8-pie - "PL", # pylint - "PT", # flake8-pytest-style - "PTH", # flake8-pathlib - "PYI", # flake8-pyi - "RET", # flake8-return - "RSE", # flake8-raise - "RUF005", # Consider iterable unpacking instead of concatenation - "RUF006", # Store a reference to the return value of asyncio.create_task - "RUF007", # Prefer itertools.pairwise() over zip() when iterating over successive pairs - "RUF008", # Do not use mutable default values for dataclass attributes - "RUF010", # Use explicit conversion flag - "RUF013", # PEP 484 prohibits implicit Optional - "RUF016", # Slice in indexed access to type {value_type} uses type {index_type} instead of an integer - "RUF017", # Avoid quadratic list summation - "RUF018", # Avoid assignment expressions in assert statements - "RUF019", # Unnecessary key check before dictionary access - "RUF020", # {never_like} | T is equivalent to T - "RUF021", # Parenthesize a and b expressions when chaining and and or together, to make the precedence clear - "RUF022", # Sort __all__ - "RUF023", # Sort __slots__ - "RUF024", # Do not pass mutable objects as values to dict.fromkeys - "RUF026", # default_factory is a positional-only argument to defaultdict - "RUF030", # print() call in assert statement is likely unintentional - "RUF032", # Decimal() called with float literal argument - "RUF033", # __post_init__ method with argument defaults - "RUF034", # Useless if-else condition - "RUF100", # Unused `noqa` directive - "RUF101", # noqa directives that use redirected rule codes - "RUF200", # Failed to parse pyproject.toml: {message} - "S102", # Use of exec detected - "S103", # bad-file-permissions - "S108", # hardcoded-temp-file - "S306", # suspicious-mktemp-usage - "S307", # suspicious-eval-usage - "S313", # suspicious-xmlc-element-tree-usage - "S314", # suspicious-xml-element-tree-usage - "S315", # suspicious-xml-expat-reader-usage - "S316", # suspicious-xml-expat-builder-usage - "S317", # suspicious-xml-sax-usage - "S318", # suspicious-xml-mini-dom-usage - "S319", # suspicious-xml-pull-dom-usage - "S601", # paramiko-call - "S602", # subprocess-popen-with-shell-equals-true - "S604", # call-with-shell-equals-true - "S608", # hardcoded-sql-expression - "S609", # unix-command-wildcard-injection - "SIM", # flake8-simplify - "SLF", # flake8-self - "SLOT", # flake8-slots - "T100", # Trace found: {name} used - "T20", # flake8-print - "TC", # flake8-type-checking - "TID", # Tidy imports - "TRY", # tryceratops - "UP", # pyupgrade - "UP031", # Use format specifiers instead of percent format - "UP032", # Use f-string instead of `format` call - "W", # pycodestyle + "C", # complexity + "COM818", # Trailing comma on bare tuple prohibited + "D", # docstrings + "DTZ003", # Use datetime.now(tz=) instead of datetime.utcnow() + "DTZ004", # Use datetime.fromtimestamp(ts, tz=) instead of datetime.utcfromtimestamp(ts) + "E", # pycodestyle + "F", # pyflakes/autoflake + "F541", # f-string without any placeholders + "FLY", # flynt + "FURB", # refurb + "G", # flake8-logging-format + "I", # isort + "INP", # flake8-no-pep420 + "ISC", # flake8-implicit-str-concat + "ICN001", # import concentions; {name} should be imported as {asname} + "LOG", # flake8-logging + "N804", # First argument of a class method should be named cls + "N805", # First argument of a method should be named self + "N815", # Variable {name} in class scope should not be mixedCase + "PERF", # Perflint + "PGH", # pygrep-hooks + "PIE", # flake8-pie + "PL", # pylint + "PT", # flake8-pytest-style + "PTH", # flake8-pathlib + "PYI", # flake8-pyi + "RET", # flake8-return + "RSE", # flake8-raise + "RUF005", # Consider iterable unpacking instead of concatenation + "RUF006", # Store a reference to the return value of asyncio.create_task + "RUF007", # Prefer itertools.pairwise() over zip() when iterating over successive pairs + "RUF008", # Do not use mutable default values for dataclass attributes + "RUF010", # Use explicit conversion flag + "RUF013", # PEP 484 prohibits implicit Optional + "RUF016", # Slice in indexed access to type {value_type} uses type {index_type} instead of an integer + "RUF017", # Avoid quadratic list summation + "RUF018", # Avoid assignment expressions in assert statements + "RUF019", # Unnecessary key check before dictionary access + "RUF020", # {never_like} | T is equivalent to T + "RUF021", # Parenthesize a and b expressions when chaining and and or together, to make the precedence clear + "RUF022", # Sort __all__ + "RUF023", # Sort __slots__ + "RUF024", # Do not pass mutable objects as values to dict.fromkeys + "RUF026", # default_factory is a positional-only argument to defaultdict + "RUF030", # print() call in assert statement is likely unintentional + "RUF032", # Decimal() called with float literal argument + "RUF033", # __post_init__ method with argument defaults + "RUF034", # Useless if-else condition + "RUF100", # Unused `noqa` directive + "RUF101", # noqa directives that use redirected rule codes + "RUF200", # Failed to parse pyproject.toml: {message} + "S102", # Use of exec detected + "S103", # bad-file-permissions + "S108", # hardcoded-temp-file + "S306", # suspicious-mktemp-usage + "S307", # suspicious-eval-usage + "S313", # suspicious-xmlc-element-tree-usage + "S314", # suspicious-xml-element-tree-usage + "S315", # suspicious-xml-expat-reader-usage + "S316", # suspicious-xml-expat-builder-usage + "S317", # suspicious-xml-sax-usage + "S318", # suspicious-xml-mini-dom-usage + "S319", # suspicious-xml-pull-dom-usage + "S601", # paramiko-call + "S602", # subprocess-popen-with-shell-equals-true + "S604", # call-with-shell-equals-true + "S608", # hardcoded-sql-expression + "S609", # unix-command-wildcard-injection + "SIM", # flake8-simplify + "SLF", # flake8-self + "SLOT", # flake8-slots + "T100", # Trace found: {name} used + "T20", # flake8-print + "TC", # flake8-type-checking + "TID", # Tidy imports + "TRY", # tryceratops + "UP", # pyupgrade + "UP031", # Use format specifiers instead of percent format + "UP032", # Use f-string instead of `format` call + "W", # pycodestyle ] +[dependency-groups] +dev = [ + "pytest-cov>=7.0.0", +] diff --git a/src/alpine_bits_python/__init__.py b/src/alpine_bits_python/__init__.py index e69de29..85f5b0f 100644 --- a/src/alpine_bits_python/__init__.py +++ b/src/alpine_bits_python/__init__.py @@ -0,0 +1 @@ +"""AlpineBits Python Server package.""" diff --git a/src/alpine_bits_python/__main__.py b/src/alpine_bits_python/__main__.py deleted file mode 100644 index a9e3250..0000000 --- a/src/alpine_bits_python/__main__.py +++ /dev/null @@ -1,7 +0,0 @@ -"""Entry point for alpine_bits_python package.""" - -from .main import main - -if __name__ == "__main__": - print("running test main") - main() diff --git a/src/alpine_bits_python/alpine_bits_helpers.py b/src/alpine_bits_python/alpine_bits_helpers.py index 6d367f6..0e0adf4 100644 --- a/src/alpine_bits_python/alpine_bits_helpers.py +++ b/src/alpine_bits_python/alpine_bits_helpers.py @@ -1,11 +1,11 @@ -import logging import traceback from dataclasses import dataclass -from datetime import UTC, datetime +from datetime import UTC from enum import Enum from typing import Any from alpine_bits_python.db import Customer, Reservation +from alpine_bits_python.logging_config import get_logger from alpine_bits_python.schemas import ( CommentData, CommentListItemData, @@ -25,8 +25,7 @@ from .generated.alpinebits import ( UniqueIdType2, ) -_LOGGER = logging.getLogger(__name__) -_LOGGER.setLevel(logging.INFO) +_LOGGER = get_logger(__name__) # Define type aliases for the two Customer types NotifCustomer = OtaHotelResNotifRq.HotelReservations.HotelReservation.ResGuests.ResGuest.Profiles.ProfileInfo.Profile.Customer # noqa: E501 @@ -74,6 +73,8 @@ RetrieveRoomStays = OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays NotifHotelReservation = OtaHotelResNotifRq.HotelReservations.HotelReservation RetrieveHotelReservation = OtaResRetrieveRs.ReservationsList.HotelReservation +from .const import RESERVATION_ID_TYPE + # Enum to specify which OTA message type to use class OtaMessageType(Enum): @@ -389,8 +390,11 @@ class CommentFactory: # Create list items list_items = [] for item_data in comment_data.list_items: - _LOGGER.info( - f"Creating list item: value={item_data.value}, list_item={item_data.list_item}, language={item_data.language}" + _LOGGER.debug( + "Creating list item: value=%s, list_item=%s, language=%s", + item_data.value, + item_data.list_item, + item_data.language, ) list_item = comment_class.ListItem( @@ -601,19 +605,24 @@ class AlpineBitsFactory: def create_res_retrieve_response( - list: list[tuple[Reservation, Customer]], + list: list[tuple[Reservation, Customer]], config: dict[str, Any] ) -> OtaResRetrieveRs: """Create RetrievedReservation XML from database entries.""" - return _create_xml_from_db(list, OtaMessageType.RETRIEVE) + return _create_xml_from_db(list, OtaMessageType.RETRIEVE, config) -def create_res_notif_push_message(list: tuple[Reservation, Customer]): +def create_res_notif_push_message( + list: tuple[Reservation, Customer], config: dict[str, Any] +): """Create Reservation Notification XML from database entries.""" - return _create_xml_from_db(list, OtaMessageType.NOTIF) + return _create_xml_from_db(list, OtaMessageType.NOTIF, config) def _process_single_reservation( - reservation: Reservation, customer: Customer, message_type: OtaMessageType + reservation: Reservation, + customer: Customer, + message_type: OtaMessageType, + config: dict[str, Any], ): phone_numbers = ( [(customer.phone, PhoneTechType.MOBILE)] if customer.phone is not None else [] @@ -695,11 +704,14 @@ def _process_single_reservation( # - Trim whitespace # - Truncate to 64 characters if needed # - Convert empty strings to None + + res_id_source_context = config["server"]["res_id_source_context"] + hotel_res_id_data = HotelReservationIdData( - res_id_type="13", + res_id_type=RESERVATION_ID_TYPE, res_id_value=klick_id, res_id_source=res_id_source, - res_id_source_context="99tales", + res_id_source_context=res_id_source_context, ) hotel_res_id = alpine_bits_factory.create(hotel_res_id_data, message_type) @@ -710,10 +722,7 @@ def _process_single_reservation( if reservation.hotel_code is None: raise ValueError("Reservation hotel_code is None") hotel_code = str(reservation.hotel_code) - if reservation.hotel_name is None: - hotel_name = None - else: - hotel_name = str(reservation.hotel_name) + hotel_name = None if reservation.hotel_name is None else str(reservation.hotel_name) basic_property_info = HotelReservation.ResGlobalInfo.BasicPropertyInfo( hotel_code=hotel_code, @@ -755,15 +764,22 @@ def _process_single_reservation( comments_xml = None if comments: for c in comments: - _LOGGER.info( - f"Creating comment: name={c.name}, text={c.text}, list_items={len(c.list_items)}" + _LOGGER.debug( + "Creating comment: name=%s, text=%s, list_items=%s", + c.name, + c.text, + len(c.list_items), ) comments_data = CommentsData(comments=comments) comments_xml = alpine_bits_factory.create(comments_data, message_type) + company_name_value = config["server"]["companyname"] + company_code = config["server"]["code"] + codecontext = config["server"]["codecontext"] + company_name = Profile.CompanyInfo.CompanyName( - value="99tales GmbH", code="who knows?", code_context="who knows?" + value=company_name_value, code=company_code, code_context=codecontext ) company_info = Profile.CompanyInfo(company_name=company_name) @@ -774,7 +790,7 @@ def _process_single_reservation( profile_info = HotelReservation.ResGlobalInfo.Profiles.ProfileInfo(profile=profile) - _LOGGER.info(f"Type of profile_info: {type(profile_info)}") + _LOGGER.info("Type of profile_info: %s", type(profile_info)) profiles = HotelReservation.ResGlobalInfo.Profiles(profile_info=profile_info) @@ -785,8 +801,8 @@ def _process_single_reservation( profiles=profiles, ) - hotel_reservation = HotelReservation( - create_date_time=datetime.now(UTC).isoformat(), + return HotelReservation( + create_date_time=reservation.created_at.replace(tzinfo=UTC).isoformat(), res_status=HotelReservationResStatus.REQUESTED, room_stay_reservation="true", unique_id=unique_id, @@ -795,12 +811,11 @@ def _process_single_reservation( res_global_info=res_global_info, ) - return hotel_reservation - def _create_xml_from_db( entries: list[tuple[Reservation, Customer]] | tuple[Reservation, Customer], type: OtaMessageType, + config: dict[str, Any], ): """Create RetrievedReservation XML from database entries. @@ -815,17 +830,23 @@ def _create_xml_from_db( for reservation, customer in entries: _LOGGER.info( - f"Creating XML for reservation {reservation.unique_id} and customer {customer.given_name}" + "Creating XML for reservation %s and customer %s", + reservation.id, + customer.id, ) try: - hotel_reservation = _process_single_reservation(reservation, customer, type) + hotel_reservation = _process_single_reservation( + reservation, customer, type, config + ) reservations_list.append(hotel_reservation) - except Exception as e: - _LOGGER.error( - f"Error creating XML for reservation {reservation.unique_id} and customer {customer.given_name}: {e}" + except Exception: + _LOGGER.exception( + "Error creating XML for reservation %s and customer %s", + reservation.unique_id, + customer.given_name, ) _LOGGER.debug(traceback.format_exc()) @@ -840,8 +861,8 @@ def _create_xml_from_db( try: ota_hotel_res_notif_rq.model_validate(ota_hotel_res_notif_rq.model_dump()) - except Exception as e: - _LOGGER.error(f"Validation error: {e}") + except Exception: + _LOGGER.exception("Validation error: ") raise return ota_hotel_res_notif_rq @@ -857,195 +878,9 @@ def _create_xml_from_db( try: ota_res_retrieve_rs.model_validate(ota_res_retrieve_rs.model_dump()) except Exception as e: - _LOGGER.error(f"Validation error: {e}") + _LOGGER.exception(f"Validation error: {e}") raise return ota_res_retrieve_rs raise ValueError(f"Unsupported message type: {type}") - - -# Usage examples -if __name__ == "__main__": - # Create customer data using simple data class - customer_data = CustomerData( - given_name="John", - surname="Doe", - name_prefix="Mr.", - phone_numbers=[ - ("+1234567890", PhoneTechType.MOBILE), # Phone number with type - ("+0987654321", None), # Phone number without type - ], - email_address="john.doe@example.com", - email_newsletter=True, - address_line="123 Main Street", - city_name="Anytown", - postal_code="12345", - country_code="US", - address_catalog=False, - gender="Male", - birth_date="1980-01-01", - language="en", - ) - - # Create customer for OtaHotelResNotifRq - notif_customer = CustomerFactory.create_notif_customer(customer_data) - print( - "Created NotifCustomer:", - notif_customer.person_name.given_name, - notif_customer.person_name.surname, - ) - - # Create customer for OtaResRetrieveRs - retrieve_customer = CustomerFactory.create_retrieve_customer(customer_data) - print( - "Created RetrieveCustomer:", - retrieve_customer.person_name.given_name, - retrieve_customer.person_name.surname, - ) - - # Convert back to data class - converted_data = CustomerFactory.from_notif_customer(notif_customer) - print("Converted back to data:", converted_data.given_name, converted_data.surname) - - # Verify they contain the same information - print("Original and converted data match:", customer_data == converted_data) - - print("\n--- HotelReservationIdFactory Examples ---") - - # Create hotel reservation ID data - reservation_id_data = HotelReservationIdData( - res_id_type="123", - res_id_value="RESERVATION-456", - res_id_source="HOTEL_SYSTEM", - res_id_source_context="BOOKING_ENGINE", - ) - - # Create HotelReservationId for both types - notif_res_id = HotelReservationIdFactory.create_notif_hotel_reservation_id( - reservation_id_data - ) - retrieve_res_id = HotelReservationIdFactory.create_retrieve_hotel_reservation_id( - reservation_id_data - ) - - print( - "Created NotifHotelReservationId:", - notif_res_id.res_id_type, - notif_res_id.res_id_value, - ) - print( - "Created RetrieveHotelReservationId:", - retrieve_res_id.res_id_type, - retrieve_res_id.res_id_value, - ) - - # Convert back to data class - converted_res_id_data = HotelReservationIdFactory.from_notif_hotel_reservation_id( - notif_res_id - ) - print( - "Converted back to reservation ID data:", - converted_res_id_data.res_id_type, - converted_res_id_data.res_id_value, - ) - - # Verify they contain the same information - print( - "Original and converted reservation ID data match:", - reservation_id_data == converted_res_id_data, - ) - - print("\n--- ResGuestFactory Examples ---") - - # Create complete ResGuests structure for OtaHotelResNotifRq - much simpler! - notif_res_guests = ResGuestFactory.create_notif_res_guests(customer_data) - print( - "Created NotifResGuests with customer:", - notif_res_guests.res_guest.profiles.profile_info.profile.customer.person_name.given_name, - ) - - # Create complete ResGuests structure for OtaResRetrieveRs - much simpler! - retrieve_res_guests = ResGuestFactory.create_retrieve_res_guests(customer_data) - print( - "Created RetrieveResGuests with customer:", - retrieve_res_guests.res_guest.profiles.profile_info.profile.customer.person_name.given_name, - ) - - # Extract primary customer data back from ResGuests structure - extracted_data = ResGuestFactory.extract_primary_customer(retrieve_res_guests) - print("Extracted customer data:", extracted_data.given_name, extracted_data.surname) - - # Verify roundtrip conversion - print("Roundtrip conversion successful:", customer_data == extracted_data) - - print("\n--- Unified AlpineBitsFactory Examples ---") - - # Much simpler approach - single factory with enum parameter! - print("=== Customer Creation ===") - notif_customer = AlpineBitsFactory.create(customer_data, OtaMessageType.NOTIF) - retrieve_customer = AlpineBitsFactory.create(customer_data, OtaMessageType.RETRIEVE) - print("Created customers using unified factory") - - print("=== HotelReservationId Creation ===") - reservation_id_data = HotelReservationIdData( - res_id_type="123", res_id_value="RESERVATION-456", res_id_source="HOTEL_SYSTEM" - ) - notif_res_id = AlpineBitsFactory.create(reservation_id_data, OtaMessageType.NOTIF) - retrieve_res_id = AlpineBitsFactory.create( - reservation_id_data, OtaMessageType.RETRIEVE - ) - print("Created reservation IDs using unified factory") - - print("=== Comments Creation ===") - comments_data = CommentsData( - comments=[ - CommentData( - name=CommentName2.CUSTOMER_COMMENT, - text="This is a customer comment about the reservation", - list_items=[ - CommentListItemData( - value="Special dietary requirements: vegetarian", - list_item="1", - language="en", - ), - CommentListItemData( - value="Late arrival expected", list_item="2", language="en" - ), - ], - ), - CommentData( - name=CommentName2.ADDITIONAL_INFO, - text="Additional information about the stay", - ), - ] - ) - notif_comments = AlpineBitsFactory.create(comments_data, OtaMessageType.NOTIF) - retrieve_comments = AlpineBitsFactory.create(comments_data, OtaMessageType.RETRIEVE) - print("Created comments using unified factory") - - print("=== ResGuests Creation ===") - notif_res_guests = AlpineBitsFactory.create_res_guests( - customer_data, OtaMessageType.NOTIF - ) - retrieve_res_guests = AlpineBitsFactory.create_res_guests( - customer_data, OtaMessageType.RETRIEVE - ) - print("Created ResGuests using unified factory") - - print("=== Data Extraction ===") - # Extract data back using unified interface - extracted_customer_data = AlpineBitsFactory.extract_data(notif_customer) - extracted_res_id_data = AlpineBitsFactory.extract_data(notif_res_id) - extracted_comments_data = AlpineBitsFactory.extract_data(retrieve_comments) - extracted_from_res_guests = AlpineBitsFactory.extract_data(retrieve_res_guests) - - print("Data extraction successful:") - print("- Customer roundtrip:", customer_data == extracted_customer_data) - print("- ReservationId roundtrip:", reservation_id_data == extracted_res_id_data) - print("- Comments roundtrip:", comments_data == extracted_comments_data) - print("- ResGuests roundtrip:", customer_data == extracted_from_res_guests) - - print("\n--- Comparison with old approach ---") - print("Old way required multiple imports and knowing specific factory methods") - print("New way: single import, single factory, enum parameter to specify type!") diff --git a/src/alpine_bits_python/alpinebits_server.py b/src/alpine_bits_python/alpinebits_server.py index bb3b4a0..20404dc 100644 --- a/src/alpine_bits_python/alpinebits_server.py +++ b/src/alpine_bits_python/alpinebits_server.py @@ -7,7 +7,6 @@ handshaking functionality with configurable supported actions and capabilities. import inspect import json -import logging import re from abc import ABC from dataclasses import dataclass @@ -24,6 +23,7 @@ from alpine_bits_python.alpine_bits_helpers import ( create_res_notif_push_message, create_res_retrieve_response, ) +from alpine_bits_python.logging_config import get_logger from .db import AckedRequest, Customer, Reservation from .generated.alpinebits import ( @@ -36,8 +36,7 @@ from .generated.alpinebits import ( ) # Configure logging -logging.basicConfig(level=logging.INFO) -_LOGGER = logging.getLogger(__name__) +_LOGGER = get_logger(__name__) class HttpStatusCode(IntEnum): @@ -129,7 +128,7 @@ class Version(str, Enum): class AlpineBitsClientInfo: - """Wrapper for username, password, client_id""" + """Wrapper for username, password, client_id.""" def __init__(self, username: str, password: str, client_id: str | None = None): self.username = username @@ -213,7 +212,7 @@ class ServerCapabilities: """Discover all AlpineBitsAction implementations in the current module.""" current_module = inspect.getmodule(self) - for name, obj in inspect.getmembers(current_module): + for _name, obj in inspect.getmembers(current_module): if ( inspect.isclass(obj) and issubclass(obj, AlpineBitsAction) @@ -231,9 +230,7 @@ class ServerCapabilities: This is a simple check - in practice, you might want more sophisticated detection. """ # Check if the class has overridden the handle method - if "handle" in action_class.__dict__: - return True - return False + return "handle" in action_class.__dict__ def create_capabilities_dict(self) -> None: """Generate the capabilities dictionary based on discovered actions.""" @@ -344,7 +341,7 @@ class PingAction(AlpineBitsAction): # compare echo data with capabilities, create a dictionary containing the matching capabilities capabilities_dict = server_capabilities.get_capabilities_dict() - _LOGGER.info(f"Capabilities Dict: {capabilities_dict}") + _LOGGER.debug("Capabilities of Server: %s", capabilities_dict) matching_capabilities = {"versions": []} # Iterate through client's requested versions @@ -505,6 +502,9 @@ class ReadAction(AlpineBitsAction): start_date = None + """When given, the server will send only inquiries generated after the Start timestamp, regardless + whether the client has retrieved them before or not.""" + if hotel_read_request.selection_criteria is not None: start_date = datetime.fromisoformat( hotel_read_request.selection_criteria.start @@ -518,7 +518,8 @@ class ReadAction(AlpineBitsAction): .filter(Reservation.hotel_code == hotelid) ) if start_date: - stmt = stmt.filter(Reservation.start_date >= start_date) + _LOGGER.info("Filtering reservations from start date %s", start_date) + stmt = stmt.filter(Reservation.created_at >= start_date) # remove reservations that have been acknowledged via client_id elif client_info.client_id: subquery = ( @@ -537,14 +538,20 @@ class ReadAction(AlpineBitsAction): ) # List of (Reservation, Customer) tuples _LOGGER.info( - f"Querying reservations and customers for hotel {hotelid} from database" + "Querying reservations and customers for hotel %s from database", + hotelid, ) for reservation, customer in reservation_customer_pairs: _LOGGER.info( - f"Reservation: {reservation.id}, Customer: {customer.given_name}" + "Retrieving reservation %s for customer %s %s", + reservation.id, + customer.given_name, + customer.surname, ) - res_retrive_rs = create_res_retrieve_response(reservation_customer_pairs) + res_retrive_rs = create_res_retrieve_response( + reservation_customer_pairs, config=self.config + ) config = SerializerConfig( pretty_print=True, xml_declaration=True, encoding="UTF-8" @@ -558,7 +565,7 @@ class ReadAction(AlpineBitsAction): class NotifReportReadAction(AlpineBitsAction): - """Necessary for read action to follow specification. Clients need to report acknowledgements""" + """Necessary for read action to follow specification. Clients need to report acknowledgements.""" def __init__(self, config: dict = {}): self.name = AlpineBitsActionName.OTA_HOTEL_NOTIF_REPORT @@ -627,7 +634,7 @@ class NotifReportReadAction(AlpineBitsAction): class PushAction(AlpineBitsAction): - """Creates the necessary xml for OTA_HotelResNotif:GuestRequests""" + """Creates the necessary xml for OTA_HotelResNotif:GuestRequests.""" def __init__(self, config: dict = {}): self.name = AlpineBitsActionName.OTA_HOTEL_RES_NOTIF_GUEST_REQUESTS @@ -644,7 +651,9 @@ class PushAction(AlpineBitsAction): server_capabilities=None, ) -> AlpineBitsResponse: """Create push request XML.""" - xml_push_request = create_res_notif_push_message(request_xml) + xml_push_request = create_res_notif_push_message( + request_xml, config=self.config + ) config = SerializerConfig( pretty_print=True, xml_declaration=True, encoding="UTF-8" @@ -665,7 +674,7 @@ class AlpineBitsServer: their capabilities, and can respond to handshake requests with its capabilities. """ - def __init__(self, config: dict = None): + def __init__(self, config: dict | None = None): self.capabilities = ServerCapabilities() self._action_instances = {} self.config = config @@ -771,7 +780,6 @@ class AlpineBitsServer: client_info=client_info, ) except Exception as e: - print(f"Error handling request {request_action_name}: {e!s}") # print stack trace for debugging import traceback @@ -784,7 +792,7 @@ class AlpineBitsServer: def get_supported_request_names(self) -> list[str]: """Get all supported request names (not capability names).""" request_names = [] - for capability_name in self._action_instances.keys(): + for capability_name in self._action_instances: action_enum = AlpineBitsActionName.get_by_capability_name(capability_name) if action_enum: request_names.append(action_enum.request_name) diff --git a/src/alpine_bits_python/api.py b/src/alpine_bits_python/api.py index f527e6e..422e26b 100644 --- a/src/alpine_bits_python/api.py +++ b/src/alpine_bits_python/api.py @@ -1,11 +1,10 @@ import asyncio import gzip import json -import logging import os import urllib.parse from collections import defaultdict -from datetime import UTC, date, datetime +from datetime import date, datetime from functools import partial from pathlib import Path from typing import Any @@ -16,6 +15,7 @@ from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import HTMLResponse, Response from fastapi.security import HTTPBasic, HTTPBasicCredentials from slowapi.errors import RateLimitExceeded +from sqlalchemy import select from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine from alpine_bits_python.schemas import ReservationData @@ -26,11 +26,12 @@ from .alpinebits_server import ( AlpineBitsServer, Version, ) -from .auth import generate_api_key, generate_unique_id, validate_api_key +from .auth import generate_unique_id, validate_api_key from .config_loader import load_config from .db import Base, get_database_url from .db import Customer as DBCustomer from .db import Reservation as DBReservation +from .logging_config import get_logger, setup_logging from .rate_limit import ( BURST_RATE_LIMIT, DEFAULT_RATE_LIMIT, @@ -40,9 +41,8 @@ from .rate_limit import ( webhook_limiter, ) -# Configure logging -logging.basicConfig(level=logging.INFO) -_LOGGER = logging.getLogger(__name__) +# Configure logging - will be reconfigured during lifespan with actual config +_LOGGER = get_logger(__name__) # HTTP Basic auth for AlpineBits security_basic = HTTPBasic() @@ -58,7 +58,7 @@ class EventDispatcher: self.listeners[event_name].append(func) def register_hotel_listener(self, event_name, hotel_code, func): - """Register a listener for a specific hotel""" + """Register a listener for a specific hotel.""" self.hotel_listeners[f"{event_name}:{hotel_code}"].append(func) async def dispatch(self, event_name, *args, **kwargs): @@ -66,7 +66,7 @@ class EventDispatcher: await func(*args, **kwargs) async def dispatch_for_hotel(self, event_name, hotel_code, *args, **kwargs): - """Dispatch event only to listeners registered for specific hotel""" + """Dispatch event only to listeners registered for specific hotel.""" key = f"{event_name}:{hotel_code}" for func in self.hotel_listeners[key]: await func(*args, **kwargs) @@ -79,12 +79,13 @@ event_dispatcher = EventDispatcher() async def push_listener(customer: DBCustomer, reservation: DBReservation, hotel): """Push listener that sends reservation data to hotel's push endpoint. + Only called for reservations that match this hotel's hotel_id. """ push_endpoint = hotel.get("push_endpoint") if not push_endpoint: _LOGGER.warning( - f"No push endpoint configured for hotel {hotel.get('hotel_id')}" + "No push endpoint configured for hotel %s", hotel.get("hotel_id") ) return @@ -95,12 +96,16 @@ async def push_listener(customer: DBCustomer, reservation: DBReservation, hotel) # Double-check hotel matching (should be guaranteed by dispatcher) if hotel_id != reservation_hotel_id: _LOGGER.warning( - f"Hotel ID mismatch: listener for {hotel_id}, reservation for {reservation_hotel_id}" + "Hotel ID mismatch: listener for %s, reservation for %s", + hotel_id, + reservation_hotel_id, ) return _LOGGER.info( - f"Processing push notification for hotel {hotel_id}, reservation {reservation.unique_id}" + "Processing push notification for hotel %s, reservation %s", + hotel_id, + reservation.unique_id, ) # Prepare payload for push notification @@ -114,15 +119,18 @@ async def push_listener(customer: DBCustomer, reservation: DBReservation, hotel) if request.status_code != 200: _LOGGER.error( - f"Failed to generate push request for hotel {hotel_id}, reservation {reservation.unique_id}: {request.xml_content}" + "Failed to generate push request for hotel %s, reservation %s: %s", + hotel_id, + reservation.unique_id, + request.xml_content, ) return # save push request to file logs_dir = "logs/push_requests" - if not os.path.exists(logs_dir): - os.makedirs(logs_dir, mode=0o755, exist_ok=True) + if not Path.exists(logs_dir): + Path.mkdir(logs_dir, mode=0o755, exist_ok=True) stat_info = os.stat(logs_dir) _LOGGER.info( f"Created directory owner: uid:{stat_info.st_uid}, gid:{stat_info.st_gid}" @@ -155,7 +163,7 @@ async def push_listener(customer: DBCustomer, reservation: DBReservation, hotel) ) except Exception as e: - _LOGGER.error(f"Push event failed for hotel {hotel['hotel_id']}: {e}") + _LOGGER.exception(f"Push event failed for hotel {hotel['hotel_id']}: {e}") # Optionally implement retry logic here@asynccontextmanager @@ -164,12 +172,16 @@ async def lifespan(app: FastAPI): try: config = load_config() - except Exception as e: - _LOGGER.error(f"Failed to load config: {e!s}") + except Exception: + _LOGGER.exception("Failed to load config: ") config = {} + # Setup logging from config + setup_logging(config) + _LOGGER.info("Application startup initiated") + DATABASE_URL = get_database_url(config) - engine = create_async_engine(DATABASE_URL, echo=True) + engine = create_async_engine(DATABASE_URL, echo=False) AsyncSessionLocal = async_sessionmaker(engine, expire_on_commit=False) app.state.engine = engine @@ -189,12 +201,14 @@ async def lifespan(app: FastAPI): "form_processed", hotel_id, partial(push_listener, hotel=hotel) ) _LOGGER.info( - f"Registered push listener for hotel {hotel_id} with endpoint {push_endpoint.get('url')}" + "Registered push listener for hotel %s with endpoint %s", + hotel_id, + push_endpoint.get("url"), ) elif push_endpoint and not hotel_id: - _LOGGER.warning(f"Hotel has push_endpoint but no hotel_id: {hotel}") + _LOGGER.warning("Hotel has push_endpoint but no hotel_id: %s", hotel) elif hotel_id and not push_endpoint: - _LOGGER.info(f"Hotel {hotel_id} has no push_endpoint configured") + _LOGGER.info("Hotel %s has no push_endpoint configured", hotel_id) # Create tables async with engine.begin() as conn: @@ -245,7 +259,7 @@ app.add_middleware( @api_router.get("/") @limiter.limit(DEFAULT_RATE_LIMIT) async def root(request: Request): - """Health check endpoint""" + """Health check endpoint.""" return { "message": "Wix Form Handler API is running", "timestamp": datetime.now().isoformat(), @@ -262,7 +276,7 @@ async def root(request: Request): @api_router.get("/health") @limiter.limit(DEFAULT_RATE_LIMIT) async def health_check(request: Request): - """Detailed health check""" + """Detailed health check.""" return { "status": "healthy", "timestamp": datetime.now().isoformat(), @@ -332,7 +346,7 @@ async def process_wix_form_submission(request: Request, data: dict[str, Any], db last_name = contact_info.get("name", {}).get("last") email = contact_info.get("email") phone_number = contact_info.get("phones", [{}])[0].get("e164Phone") - locale = contact_info.get("locale", "de-de") + contact_info.get("locale", "de-de") contact_id = contact_info.get("contactId") name_prefix = data.get("field:anrede") @@ -364,7 +378,7 @@ async def process_wix_form_submission(request: Request, data: dict[str, Any], db num_children = int(data.get("field:anzahl_kinder") or 0) children_ages = [] if num_children > 0: - for k in data.keys(): + for k in data: if k.startswith("field:alter_kind_"): try: age = int(data[k]) @@ -380,28 +394,57 @@ async def process_wix_form_submission(request: Request, data: dict[str, Any], db # use database session - # Save all relevant data to DB (including new fields) - db_customer = DBCustomer( - given_name=first_name, - surname=last_name, - contact_id=contact_id, - name_prefix=name_prefix, - email_address=email, - phone=phone_number, - email_newsletter=email_newsletter, - address_line=address_line, - city_name=city_name, - postal_code=postal_code, - country_code=country_code, - gender=gender, - birth_date=birth_date, - language=language, - address_catalog=False, - name_title=None, - ) - db.add(db_customer) - await db.flush() # This assigns db_customer.id without committing - # await db.refresh(db_customer) + # Check if customer with this contact_id already exists + existing_customer = None + if contact_id: + result = await db.execute( + select(DBCustomer).where(DBCustomer.contact_id == contact_id) + ) + existing_customer = result.scalar_one_or_none() + + if existing_customer: + # Update existing customer with new information + _LOGGER.info("Updating existing customer with contact_id: %s", contact_id) + existing_customer.given_name = first_name + existing_customer.surname = last_name + existing_customer.name_prefix = name_prefix + existing_customer.email_address = email + existing_customer.phone = phone_number + existing_customer.email_newsletter = email_newsletter + existing_customer.address_line = address_line + existing_customer.city_name = city_name + existing_customer.postal_code = postal_code + existing_customer.country_code = country_code + existing_customer.gender = gender + existing_customer.birth_date = birth_date + existing_customer.language = language + existing_customer.address_catalog = False + existing_customer.name_title = None + db_customer = existing_customer + await db.flush() + else: + # Create new customer + _LOGGER.info("Creating new customer with contact_id: %s", contact_id) + db_customer = DBCustomer( + given_name=first_name, + surname=last_name, + contact_id=contact_id, + name_prefix=name_prefix, + email_address=email, + phone=phone_number, + email_newsletter=email_newsletter, + address_line=address_line, + city_name=city_name, + postal_code=postal_code, + country_code=country_code, + gender=gender, + birth_date=birth_date, + language=language, + address_catalog=False, + name_title=None, + ) + db.add(db_customer) + await db.flush() # This assigns db_customer.id without committing # Determine hotel_code and hotel_name # Priority: 1) Form field, 2) Configuration default, 3) Hardcoded fallback @@ -419,6 +462,16 @@ async def process_wix_form_submission(request: Request, data: dict[str, Any], db or "Frangart Inn" # fallback ) + submissionTime = data.get("submissionTime") # 2025-10-07T05:48:41.855Z + try: + if submissionTime: + submissionTime = datetime.fromisoformat( + submissionTime[:-1] + ) # Remove Z and convert + except Exception as e: + _LOGGER.exception("Error parsing submissionTime: %s", e) + submissionTime = None + reservation = ReservationData( unique_id=unique_id, start_date=date.fromisoformat(start_date), @@ -429,7 +482,7 @@ async def process_wix_form_submission(request: Request, data: dict[str, Any], db hotel_code=hotel_code, hotel_name=hotel_name, offer=offer, - created_at=datetime.now(UTC), + created_at=submissionTime, utm_source=data.get("field:utm_source"), utm_medium=data.get("field:utm_medium"), utm_campaign=data.get("field:utm_campaign"), @@ -519,17 +572,18 @@ async def handle_wix_form( request: Request, data: dict[str, Any], db_session=Depends(get_async_session) ): """Unified endpoint to handle Wix form submissions (test and production). + No authentication required for this endpoint. """ try: return await process_wix_form_submission(request, data, db_session) except Exception as e: - _LOGGER.error(f"Error in handle_wix_form: {e!s}") + _LOGGER.exception("Error in handle_wix_form: %s", e) # log stacktrace import traceback traceback_str = traceback.format_exc() - _LOGGER.error(f"Stack trace for handle_wix_form: {traceback_str}") + _LOGGER.exception("Stack trace for handle_wix_form: %s", traceback_str) raise HTTPException(status_code=500, detail="Error processing Wix form data") @@ -539,25 +593,90 @@ async def handle_wix_form_test( request: Request, data: dict[str, Any], db_session=Depends(get_async_session) ): """Test endpoint to verify the API is working with raw JSON data. + No authentication required for testing purposes. """ try: return await process_wix_form_submission(request, data, db_session) except Exception as e: - _LOGGER.error(f"Error in handle_wix_form_test: {e!s}") + _LOGGER.exception(f"Error in handle_wix_form_test: {e!s}") raise HTTPException(status_code=500, detail="Error processing test data") -@api_router.post("/hoteldata/conversions_import") -@limiter.limit(DEFAULT_RATE_LIMIT) -async def handle_xml_upload( - request: Request, credentials_tupel: tuple = Depends(validate_basic_auth) -): - """Endpoint for receiving XML files for conversion processing. - Requires basic authentication and saves XML files to log directory. - Supports gzip compression via Content-Encoding header. +@api_router.post("/webhook/generic") +@webhook_limiter.limit(WEBHOOK_RATE_LIMIT) +async def handle_generic_webhook(request: Request, data: dict[str, Any]): + """Handle generic webhook endpoint for receiving JSON payloads. + + Logs the data to file for later analysis. Does not process the data + or save to database since the structure is not yet known. + + No authentication required for this endpoint. """ try: + timestamp = datetime.now().isoformat() + _LOGGER.info("Received generic webhook data at %s", timestamp) + + # Create log entry with metadata + log_entry = { + "timestamp": timestamp, + "client_ip": request.client.host if request.client else "unknown", + "headers": dict(request.headers), + "data": data, + "origin_header": request.headers.get("origin"), + } + + # Create logs directory if it doesn't exist + logs_dir = Path("logs/generic_webhooks") + if not logs_dir.exists(): + logs_dir.mkdir(parents=True, mode=0o755, exist_ok=True) + _LOGGER.info("Created directory: %s", logs_dir) + + # Generate log filename with timestamp + log_filename = ( + logs_dir / f"webhook_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" + ) + + # Write log file + with log_filename.open("w", encoding="utf-8") as f: + json.dump(log_entry, f, indent=2, default=str, ensure_ascii=False) + + _LOGGER.info("Generic webhook data logged to: %s", log_filename) + + except Exception as e: + _LOGGER.exception("Error in handle_generic_webhook") + raise HTTPException( + status_code=500, detail="Error processing generic webhook data" + ) from e + else: + return { + "status": "success", + "message": "Generic webhook data received successfully", + "data_logged_to": str(log_filename), + "timestamp": timestamp, + "note": "Data logged for later analysis", + } + + +@api_router.put("/hoteldata/conversions_import/{filename:path}") +@limiter.limit(DEFAULT_RATE_LIMIT) +async def handle_xml_upload( + request: Request, + filename: str, + credentials_tupel: tuple = Depends(validate_basic_auth), +): + """Endpoint for receiving XML files for conversion processing via PUT. + + Requires basic authentication and saves XML files to log directory. + Supports gzip compression via Content-Encoding header. + + Example: PUT /api/hoteldata/conversions_import/Reservierungen.xml + """ + try: + # Validate filename to prevent path traversal + if ".." in filename or filename.startswith("/"): + raise HTTPException(status_code=400, detail="ERROR: Invalid filename") + # Get the raw body content body = await request.body() @@ -602,12 +721,20 @@ async def handle_xml_upload( # Generate filename with timestamp and authenticated user username, _ = credentials_tupel timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") - log_filename = logs_dir / f"xml_import_{username}_{timestamp}.xml" + # Use the filename from the path, but add timestamp and username for uniqueness + base_filename = Path(filename).stem + extension = Path(filename).suffix or ".xml" + log_filename = logs_dir / f"{base_filename}_{username}_{timestamp}{extension}" # Save XML content to file log_filename.write_text(xml_content, encoding="utf-8") - _LOGGER.info("XML file saved to %s by user %s", log_filename, username) + _LOGGER.info( + "XML file saved to %s by user %s (original: %s)", + log_filename, + username, + filename, + ) response_headers = { "Content-Type": "application/xml; charset=utf-8", @@ -625,30 +752,6 @@ async def handle_xml_upload( raise HTTPException(status_code=500, detail="Error processing XML upload") -# UNUSED -@api_router.post("/admin/generate-api-key") -@limiter.limit("5/hour") # Very restrictive for admin operations -async def generate_new_api_key( - request: Request, admin_key: str = Depends(validate_api_key) -): - """Admin endpoint to generate new API keys. - Requires admin API key and is heavily rate limited. - """ - if admin_key != "admin-key": - raise HTTPException(status_code=403, detail="Admin access required") - - new_key = generate_api_key() - _LOGGER.info(f"Generated new API key (requested by: {admin_key})") - - return { - "status": "success", - "message": "New API key generated", - "api_key": new_key, - "timestamp": datetime.now().isoformat(), - "note": "Store this key securely - it won't be shown again", - } - - # TODO Bit sketchy. May need requests-toolkit in the future def parse_multipart_data(content_type: str, body: bytes) -> dict[str, Any]: """Parse multipart/form-data from raw request body. @@ -820,7 +923,7 @@ async def alpinebits_server_handshake( # Re-raise HTTP exceptions (auth errors, etc.) raise except Exception as e: - _LOGGER.error(f"Error in AlpineBits handshake: {e!s}") + _LOGGER.exception(f"Error in AlpineBits handshake: {e!s}") raise HTTPException(status_code=500, detail="Internal server error") diff --git a/src/alpine_bits_python/auth.py b/src/alpine_bits_python/auth.py index 6f32046..0ca4ecd 100644 --- a/src/alpine_bits_python/auth.py +++ b/src/alpine_bits_python/auth.py @@ -1,6 +1,5 @@ import hashlib import hmac -import logging import os import secrets @@ -10,8 +9,9 @@ from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer # Load environment variables from .env file load_dotenv() +from .logging_config import get_logger -logger = logging.getLogger(__name__) +logger = get_logger(__name__) # Security scheme security = HTTPBearer() @@ -31,12 +31,12 @@ if os.getenv("ADMIN_API_KEY"): def generate_unique_id() -> str: - """Generate a unique ID with max length 35 characters""" - return secrets.token_urlsafe(26)[:35] # 26 bytes -> 35 chars in base64url + """Generate a unique ID with max length 32 characters.""" + return secrets.token_urlsafe(26)[:32] # 26 bytes -> 32 chars in base64url def generate_api_key() -> str: - """Generate a secure API key""" + """Generate a secure API key.""" return f"sk_live_{secrets.token_urlsafe(32)}" @@ -44,6 +44,7 @@ def validate_api_key( credentials: HTTPAuthorizationCredentials = Security(security), ) -> str: """Validate API key from Authorization header. + Expected format: Authorization: Bearer your_api_key_here """ token = credentials.credentials @@ -64,6 +65,7 @@ def validate_api_key( def validate_wix_signature(payload: bytes, signature: str, secret: str) -> bool: """Validate Wix webhook signature for additional security. + Wix signs their webhooks with HMAC-SHA256. """ if not signature or not secret: @@ -81,29 +83,29 @@ def validate_wix_signature(payload: bytes, signature: str, secret: str) -> bool: # Compare signatures securely return secrets.compare_digest(signature, expected_signature) except Exception as e: - logger.error(f"Error validating signature: {e}") + logger.exception(f"Error validating signature: {e}") return False class APIKeyAuth: - """Simple API key authentication class""" + """Simple API key authentication class.""" def __init__(self, api_keys: dict): self.api_keys = api_keys def authenticate(self, api_key: str) -> str | None: - """Authenticate an API key and return the key name if valid""" + """Authenticate an API key and return the key name if valid.""" for key_name, valid_key in self.api_keys.items(): if secrets.compare_digest(api_key, valid_key): return key_name return None def add_key(self, name: str, key: str): - """Add a new API key""" + """Add a new API key.""" self.api_keys[name] = key def remove_key(self, name: str): - """Remove an API key""" + """Remove an API key.""" if name in self.api_keys: del self.api_keys[name] diff --git a/src/alpine_bits_python/config_loader.py b/src/alpine_bits_python/config_loader.py index 2da722f..168a916 100644 --- a/src/alpine_bits_python/config_loader.py +++ b/src/alpine_bits_python/config_loader.py @@ -1,12 +1,8 @@ import os from pathlib import Path -from annotatedyaml.loader import ( - Secrets, -) -from annotatedyaml.loader import ( - load_yaml as load_annotated_yaml, -) +from annotatedyaml.loader import Secrets +from annotatedyaml.loader import load_yaml as load_annotated_yaml from voluptuous import ( PREVENT_EXTRA, All, @@ -17,20 +13,68 @@ from voluptuous import ( Schema, ) +from alpine_bits_python.const import ( + CONF_ALPINE_BITS_AUTH, + CONF_DATABASE, + CONF_HOTEL_ID, + CONF_HOTEL_NAME, + CONF_LOGGING, + CONF_LOGGING_FILE, + CONF_LOGGING_LEVEL, + CONF_PASSWORD, + CONF_PUSH_ENDPOINT, + CONF_PUSH_TOKEN, + CONF_PUSH_URL, + CONF_PUSH_USERNAME, + CONF_SERVER, + CONF_SERVER_CODE, + CONF_SERVER_CODECONTEXT, + CONF_SERVER_COMPANYNAME, + CONF_SERVER_RES_ID_SOURCE_CONTEXT, + CONF_USERNAME, + ENV_ALPINE_BITS_CONFIG_PATH, +) + # --- Voluptuous schemas --- database_schema = Schema({Required("url"): str}, extra=PREVENT_EXTRA) +logger_schema = Schema( + { + Required(CONF_LOGGING_LEVEL, default="INFO"): str, + Optional(CONF_LOGGING_FILE): str, # If not provided, log to console + }, + extra=PREVENT_EXTRA, +) + + +def ensure_string(value): + """Ensure the value is a string.""" + if isinstance(value, str): + return value + return str(value) + + +server_info = Schema( + { + Required(CONF_SERVER_CODECONTEXT, default="ADVERTISING"): ensure_string, + Required(CONF_SERVER_CODE, default="70597314"): ensure_string, + Required(CONF_SERVER_COMPANYNAME, default="99tales Gmbh"): ensure_string, + Required(CONF_SERVER_RES_ID_SOURCE_CONTEXT, default="99tales"): ensure_string, + } +) + + hotel_auth_schema = Schema( { - Required("hotel_id"): str, - Required("hotel_name"): str, - Required("username"): str, - Required("password"): str, - Optional("push_endpoint"): { - Required("url"): str, - Required("token"): str, - Optional("username"): str, + Required(CONF_HOTEL_ID): ensure_string, + Required(CONF_HOTEL_NAME): str, + Required(CONF_USERNAME): str, + Required(CONF_PASSWORD): str, + Optional(CONF_PUSH_ENDPOINT): { + Required(CONF_PUSH_URL): str, + Required(CONF_PUSH_TOKEN): str, + Optional(CONF_PUSH_USERNAME): str, }, }, extra=PREVENT_EXTRA, @@ -40,8 +84,10 @@ 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, + Required(CONF_DATABASE): database_schema, + Required(CONF_ALPINE_BITS_AUTH): basic_auth_schema, + Required(CONF_SERVER): server_info, + Required(CONF_LOGGING): logger_schema, }, extra=PREVENT_EXTRA, ) @@ -52,20 +98,18 @@ DEFAULT_CONFIG_FILE = "config.yaml" class Config: def __init__( self, - config_folder: str | Path = None, + config_folder: str | Path | None = None, config_name: str = DEFAULT_CONFIG_FILE, testing_mode: bool = False, ): if config_folder is None: - config_folder = os.environ.get("ALPINEBITS_CONFIG_DIR") + config_folder = os.environ.get(ENV_ALPINE_BITS_CONFIG_PATH) if not config_folder: - config_folder = os.path.abspath( - os.path.join(os.path.dirname(__file__), "../../config") - ) + config_folder = Path(__file__).parent.joinpath("../../config").resolve() 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.config_path = config_folder / config_name self.secrets = Secrets(config_folder) self.testing_mode = testing_mode self._load_config() diff --git a/src/alpine_bits_python/const.py b/src/alpine_bits_python/const.py index e69de29..7e4d2ce 100644 --- a/src/alpine_bits_python/const.py +++ b/src/alpine_bits_python/const.py @@ -0,0 +1,34 @@ +from typing import Final + +RESERVATION_ID_TYPE: str = ( + "13" # Default reservation ID type for Reservation. 14 would be cancellation +) + + +CONF_LOGGING: Final[str] = "logger" + +CONF_LOGGING_LEVEL: Final[str] = "level" +CONF_LOGGING_FILE: Final[str] = "file" + + +CONF_DATABASE: Final[str] = "database" + + +CONF_SERVER: Final[str] = "server" +CONF_SERVER_CODECONTEXT: Final[str] = "codecontext" +CONF_SERVER_CODE: Final[str] = "code" +CONF_SERVER_COMPANYNAME: Final[str] = "companyname" +CONF_SERVER_RES_ID_SOURCE_CONTEXT: Final[str] = "res_id_source_context" + + +CONF_ALPINE_BITS_AUTH: Final[str] = "alpine_bits_auth" +CONF_HOTEL_ID: Final[str] = "hotel_id" +CONF_HOTEL_NAME: Final[str] = "hotel_name" +CONF_USERNAME: Final[str] = "username" +CONF_PASSWORD: Final[str] = "password" +CONF_PUSH_ENDPOINT: Final[str] = "push_endpoint" +CONF_PUSH_URL: Final[str] = "url" +CONF_PUSH_TOKEN: Final[str] = "token" +CONF_PUSH_USERNAME: Final[str] = "username" + +ENV_ALPINE_BITS_CONFIG_PATH: Final[str] = "ALPINE_BITS_CONFIG_DIR" diff --git a/src/alpine_bits_python/generated/alpinebits.py b/src/alpine_bits_python/generated/alpinebits.py index 82b4909..5c61617 100644 --- a/src/alpine_bits_python/generated/alpinebits.py +++ b/src/alpine_bits_python/generated/alpinebits.py @@ -585,8 +585,7 @@ class TextTextFormat2(Enum): class TimeUnitType(Enum): - """Defines the unit in which the time is expressed (e.g. year, day, hour). - """ + """Defines the unit in which the time is expressed (e.g. year, day, hour).""" YEAR = "Year" MONTH = "Month" diff --git a/src/alpine_bits_python/logging_config.py b/src/alpine_bits_python/logging_config.py new file mode 100644 index 0000000..2ce6181 --- /dev/null +++ b/src/alpine_bits_python/logging_config.py @@ -0,0 +1,87 @@ +"""Centralized logging configuration for AlpineBits application. + +This module sets up logging based on config and provides a function to get +loggers from anywhere in the application. +""" + +import logging +import sys +from pathlib import Path + + +def setup_logging(config: dict | None = None): + """Configure logging based on application config. + + Args: + config: Application configuration dict with optional 'logger' section + + Logger config format: + logger: + level: "INFO" # DEBUG, INFO, WARNING, ERROR, CRITICAL + file: "alpinebits.log" # Optional, logs to console if not provided + + """ + if config is None: + config = {} + + logger_config = config.get("logger", {}) + level = logger_config.get("level", "INFO").upper() + log_file = logger_config.get("file") + + # Convert string level to logging constant + numeric_level = getattr(logging, level, logging.INFO) + + # Create formatter with timestamp + formatter = logging.Formatter( + fmt="%(asctime)s - %(name)s - %(levelname)s - %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + ) + + # Get root logger + root_logger = logging.getLogger() + root_logger.setLevel(numeric_level) + + # Remove existing handlers to avoid duplicates + root_logger.handlers.clear() + + # Console handler (always add this) + console_handler = logging.StreamHandler(sys.stdout) + console_handler.setLevel(numeric_level) + console_handler.setFormatter(formatter) + root_logger.addHandler(console_handler) + + # File handler (optional) + if log_file: + log_path = Path(log_file) + + # Create logs directory if it doesn't exist + if log_path.parent != Path(): + log_path.parent.mkdir(parents=True, exist_ok=True) + + file_handler = logging.FileHandler(log_file, encoding="utf-8") + file_handler.setLevel(numeric_level) + file_handler.setFormatter(formatter) + root_logger.addHandler(file_handler) + + root_logger.info("Logging to file: %s", log_file) + + root_logger.info("Logging configured at %s level", level) + + +def get_logger(name: str) -> logging.Logger: + """Get a logger instance for the given module name. + + Usage: + from alpine_bits_python.logging_config import get_logger + + _LOGGER = get_logger(__name__) + _LOGGER.info("Something happened") + + Args: + name: Usually __name__ from the calling module + + Returns: + Configured logger instance + + """ + return logging.getLogger(name) diff --git a/src/alpine_bits_python/main.py b/src/alpine_bits_python/main.py deleted file mode 100644 index 38a303c..0000000 --- a/src/alpine_bits_python/main.py +++ /dev/null @@ -1,366 +0,0 @@ -import asyncio -import json -import logging -import os -from datetime import UTC, date, datetime - -from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine - -from .alpine_bits_helpers import ( - AlpineBitsFactory, - CommentData, - CommentListItemData, - CommentsData, - CustomerData, - GuestCountsFactory, - HotelReservationIdData, - OtaMessageType, - PhoneTechType, -) -from .config_loader import load_config - -# DB and config -from .db import ( - Base, - get_database_url, -) -from .db import ( - Customer as DBCustomer, -) -from .db import ( - Reservation as DBReservation, -) -from .generated import alpinebits as ab - -# Configure logging -logging.basicConfig(level=logging.INFO) -_LOGGER = logging.getLogger(__name__) - - -async def setup_db(config): - DATABASE_URL = get_database_url(config) - engine = create_async_engine(DATABASE_URL, echo=True) - AsyncSessionLocal = async_sessionmaker(engine, expire_on_commit=False) - - # Create tables - async with engine.begin() as conn: - await conn.run_sync(Base.metadata.create_all) - _LOGGER.info("Database tables checked/created at startup.") - - return engine, AsyncSessionLocal - - -async def main(): - 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+aiosqlite:///"): - db_path = db_url.replace("sqlite+aiosqlite:///", "") - 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) - # for now we delete the existing DB for clean testing - if os.path.exists(db_path): - os.remove(db_path) - print(f"Deleted existing SQLite DB at {db_path} for clean testing.") - - # # Ensure DB schema is created (async) - - engine, AsyncSessionLocal = await setup_db(config) - - async with engine.begin() as conn: - await conn.run_sync(Base.metadata.create_all) - - async with AsyncSessionLocal() as db: - # Load data from JSON file - json_path = os.path.join( - os.path.dirname(__file__), - "../../test_data/wix_test_data_20250928_132611.json", - ) - with open(json_path, encoding="utf-8") as f: - wix_data = json.load(f) - data = wix_data["data"]["data"] - - contact_info = data.get("contact", {}) - first_name = contact_info.get("name", {}).get("first") - last_name = contact_info.get("name", {}).get("last") - email = contact_info.get("email") - phone_number = contact_info.get("phones", [{}])[0].get("e164Phone") - locale = contact_info.get("locale", "de-de") - contact_id = contact_info.get("contactId") - - name_prefix = data.get("field:anrede") - email_newsletter = data.get("field:form_field_5a7b", "") != "Non selezionato" - address_line = None - city_name = None - postal_code = None - country_code = None - gender = None - birth_date = None - language = data.get("contact", {}).get("locale", "en")[:2] - - # Dates - start_date = ( - data.get("field:date_picker_a7c8") - or data.get("Anreisedatum") - or data.get("submissions", [{}])[1].get("value") - ) - end_date = ( - data.get("field:date_picker_7e65") - or data.get("Abreisedatum") - or data.get("submissions", [{}])[2].get("value") - ) - - # Room/guest info - num_adults = int(data.get("field:number_7cf5") or 2) - num_children = int(data.get("field:anzahl_kinder") or 0) - children_ages = [] - if num_children > 0: - for k in data.keys(): - if k.startswith("field:alter_kind_"): - try: - age = int(data[k]) - children_ages.append(age) - except ValueError: - logging.warning(f"Invalid age value for {k}: {data[k]}") - - # UTM and offer - utm_fields = [ - ("utm_Source", "utm_source"), - ("utm_Medium", "utm_medium"), - ("utm_Campaign", "utm_campaign"), - ("utm_Term", "utm_term"), - ("utm_Content", "utm_content"), - ] - utm_comment_text = [] - for label, field in utm_fields: - val = data.get(f"field:{field}") or data.get(label) - if val: - utm_comment_text.append(f"{label}: {val}") - utm_comment = " | ".join(utm_comment_text) if utm_comment_text else None - offer = data.get("field:angebot_auswaehlen") - - # Save all relevant data to DB (including new fields) - db_customer = DBCustomer( - given_name=first_name, - surname=last_name, - contact_id=contact_id, - name_prefix=name_prefix, - email_address=email, - phone=phone_number, - email_newsletter=email_newsletter, - address_line=address_line, - city_name=city_name, - postal_code=postal_code, - country_code=country_code, - gender=gender, - birth_date=birth_date, - language=language, - address_catalog=False, - name_title=None, - ) - db.add(db_customer) - await db.commit() - await db.refresh(db_customer) - - db_reservation = DBReservation( - customer_id=db_customer.id, - form_id=data.get("submissionId"), - start_date=date.fromisoformat(start_date) if start_date else None, - end_date=date.fromisoformat(end_date) if end_date else None, - num_adults=num_adults, - num_children=num_children, - children_ages=",".join(str(a) for a in children_ages), - offer=offer, - utm_comment=utm_comment, - created_at=datetime.now(UTC), - utm_source=data.get("field:utm_source"), - utm_medium=data.get("field:utm_medium"), - utm_campaign=data.get("field:utm_campaign"), - utm_term=data.get("field:utm_term"), - utm_content=data.get("field:utm_content"), - user_comment=data.get("field:long_answer_3524", ""), - fbclid=data.get("field:fbclid"), - gclid=data.get("field:gclid"), - hotel_code="123", - hotel_name="Frangart Inn", - ) - db.add(db_reservation) - await db.commit() - await db.refresh(db_reservation) - - # Now read back from DB - customer = await db.get(DBCustomer, db_reservation.customer_id) - reservation = await db.get(DBReservation, db_reservation.id) - - # Generate XML from DB data - create_xml_from_db(customer, reservation) - - await db.close() - - -def create_xml_from_db(customer: DBCustomer, reservation: DBReservation): - # Prepare data for XML - phone_numbers = [(customer.phone, PhoneTechType.MOBILE)] if customer.phone else [] - customer_data = CustomerData( - given_name=customer.given_name, - surname=customer.surname, - name_prefix=customer.name_prefix, - name_title=customer.name_title, - phone_numbers=phone_numbers, - email_address=customer.email_address, - email_newsletter=customer.email_newsletter, - address_line=customer.address_line, - city_name=customer.city_name, - postal_code=customer.postal_code, - country_code=customer.country_code, - address_catalog=customer.address_catalog, - gender=customer.gender, - birth_date=customer.birth_date, - language=customer.language, - ) - alpine_bits_factory = AlpineBitsFactory() - res_guests = alpine_bits_factory.create_res_guests( - customer_data, OtaMessageType.RETRIEVE - ) - - # Guest counts - children_ages = [int(a) for a in reservation.children_ages.split(",") if a] - guest_counts = GuestCountsFactory.create_retrieve_guest_counts( - reservation.num_adults, children_ages - ) - - # UniqueID - unique_id = ab.OtaResRetrieveRs.ReservationsList.HotelReservation.UniqueId( - type_value=ab.UniqueIdType2.VALUE_14, id=reservation.unique_id - ) - - # TimeSpan - time_span = ab.OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay.TimeSpan( - start=reservation.start_date.isoformat() if reservation.start_date else None, - end=reservation.end_date.isoformat() if reservation.end_date else None, - ) - room_stay = ( - ab.OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays.RoomStay( - time_span=time_span, - guest_counts=guest_counts, - ) - ) - room_stays = ab.OtaResRetrieveRs.ReservationsList.HotelReservation.RoomStays( - room_stay=[room_stay], - ) - - # HotelReservationId - hotel_res_id_data = HotelReservationIdData( - res_id_type="13", - res_id_value=reservation.fbclid or reservation.gclid, - res_id_source=None, - res_id_source_context="99tales", - ) - hotel_res_id = alpine_bits_factory.create( - hotel_res_id_data, OtaMessageType.RETRIEVE - ) - hotel_res_ids = ab.OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.HotelReservationIds( - hotel_reservation_id=[hotel_res_id] - ) - basic_property_info = ab.OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo.BasicPropertyInfo( - hotel_code=reservation.hotel_code, - hotel_name=reservation.hotel_name, - ) - - # Comments - offer_comment = CommentData( - name=ab.CommentName2.ADDITIONAL_INFO, - text="Angebot/Offerta", - list_items=[ - CommentListItemData( - value=reservation.offer, - language=customer.language, - list_item="1", - ) - ], - ) - comment = None - if reservation.user_comment: - comment = CommentData( - name=ab.CommentName2.CUSTOMER_COMMENT, - text=reservation.user_comment, - list_items=[ - CommentListItemData( - value="Landing page comment", - language=customer.language, - list_item="1", - ) - ], - ) - comments = [offer_comment, comment] if comment else [offer_comment] - comments_data = CommentsData(comments=comments) - comments_xml = alpine_bits_factory.create(comments_data, OtaMessageType.RETRIEVE) - - res_global_info = ( - ab.OtaResRetrieveRs.ReservationsList.HotelReservation.ResGlobalInfo( - hotel_reservation_ids=hotel_res_ids, - basic_property_info=basic_property_info, - comments=comments_xml, - ) - ) - - hotel_reservation = ab.OtaResRetrieveRs.ReservationsList.HotelReservation( - create_date_time=datetime.now(UTC).isoformat(), - res_status=ab.HotelReservationResStatus.REQUESTED, - room_stay_reservation="true", - unique_id=unique_id, - room_stays=room_stays, - res_guests=res_guests, - res_global_info=res_global_info, - ) - reservations_list = ab.OtaResRetrieveRs.ReservationsList( - hotel_reservation=[hotel_reservation] - ) - ota_res_retrieve_rs = ab.OtaResRetrieveRs( - version="7.000", success=None, reservations_list=reservations_list - ) - - # Serialize to XML - try: - ota_res_retrieve_rs.model_validate(ota_res_retrieve_rs.model_dump()) - print("✅ Pydantic validation successful!") - from xsdata.formats.dataclass.serializers.config import SerializerConfig - from xsdata_pydantic.bindings import XmlSerializer - - config = SerializerConfig( - pretty_print=True, xml_declaration=True, encoding="UTF-8" - ) - serializer = XmlSerializer(config=config) - ns_map = {None: "http://www.opentravel.org/OTA/2003/05"} - xml_string = serializer.render(ota_res_retrieve_rs, ns_map=ns_map) - with open("output.xml", "w", encoding="utf-8") as outfile: - outfile.write(xml_string) - print("✅ XML serialization successful!") - print("Generated XML written to output.xml") - print("\n📄 Generated XML:") - print(xml_string) - from xsdata_pydantic.bindings import XmlParser - - parser = XmlParser() - with open("output.xml", encoding="utf-8") as infile: - xml_content = infile.read() - parsed_result = parser.from_string(xml_content, ab.OtaResRetrieveRs) - print("✅ Round-trip validation successful!") - print( - f"Parsed reservation status: {parsed_result.reservations_list.hotel_reservation[0].res_status}" - ) - except Exception as e: - print(f"❌ Validation/Serialization failed: {e}") - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/src/alpine_bits_python/models.py b/src/alpine_bits_python/models.py deleted file mode 100644 index 359fcc0..0000000 --- a/src/alpine_bits_python/models.py +++ /dev/null @@ -1,73 +0,0 @@ -from typing import Any - -from pydantic import BaseModel, Field - - -class AlpineBitsHandshakeRequest(BaseModel): - """Model for AlpineBits handshake request data""" - - action: str = Field( - ..., description="Action parameter, typically 'OTA_Ping:Handshaking'" - ) - request_xml: str | None = Field(None, description="XML request document") - - -class ContactName(BaseModel): - """Contact name structure""" - - first: str | None = None - last: str | None = None - - -class ContactAddress(BaseModel): - """Contact address structure""" - - street: str | None = None - city: str | None = None - state: str | None = None - country: str | None = None - postalCode: str | None = None - - -class Contact(BaseModel): - """Contact information from Wix form""" - - name: ContactName | None = None - email: str | None = None - locale: str | None = None - company: str | None = None - birthdate: str | None = None - labelKeys: dict[str, Any] | None = None - contactId: str | None = None - address: ContactAddress | None = None - jobTitle: str | None = None - imageUrl: str | None = None - updatedDate: str | None = None - phone: str | None = None - createdDate: str | None = None - - -class SubmissionPdf(BaseModel): - """PDF submission structure""" - - url: str | None = None - filename: str | None = None - - -class WixFormSubmission(BaseModel): - """Model for Wix form submission data""" - - formName: str - submissions: list[dict[str, Any]] = Field(default_factory=list) - submissionTime: str - formFieldMask: list[str] = Field(default_factory=list) - submissionId: str - contactId: str - submissionsLink: str - submissionPdf: SubmissionPdf | None = None - formId: str - contact: Contact | None = None - - # Dynamic form fields - these will capture all field:* entries - class Config: - extra = "allow" # Allow additional fields not defined in the model diff --git a/src/alpine_bits_python/rate_limit.py b/src/alpine_bits_python/rate_limit.py index 97d4411..7ce9769 100644 --- a/src/alpine_bits_python/rate_limit.py +++ b/src/alpine_bits_python/rate_limit.py @@ -19,8 +19,7 @@ REDIS_URL = os.getenv("REDIS_URL", None) def get_remote_address_with_forwarded(request: Request): - """Get client IP address, considering forwarded headers from proxies/load balancers - """ + """Get client IP address, considering forwarded headers from proxies/load balancers.""" # Check for forwarded headers (common in production behind proxies) forwarded_for = request.headers.get("X-Forwarded-For") if forwarded_for: @@ -59,7 +58,7 @@ else: def get_api_key_identifier(request: Request) -> str: """Get identifier for rate limiting based on API key if available, otherwise IP - This allows different rate limits per API key + This allows different rate limits per API key. """ # Try to get API key from Authorization header auth_header = request.headers.get("Authorization") @@ -85,7 +84,7 @@ webhook_limiter = Limiter( # Custom rate limit exceeded handler def custom_rate_limit_handler(request: Request, exc: RateLimitExceeded): - """Custom handler for rate limit exceeded""" + """Custom handler for rate limit exceeded.""" logger.warning( f"Rate limit exceeded for {get_remote_address_with_forwarded(request)}: " f"{exc.detail}" diff --git a/src/alpine_bits_python/reservations.py b/src/alpine_bits_python/reservations.py deleted file mode 100644 index 5c8f238..0000000 --- a/src/alpine_bits_python/reservations.py +++ /dev/null @@ -1,2 +0,0 @@ -def parse_form(form: dict): - pass diff --git a/src/alpine_bits_python/run_api.py b/src/alpine_bits_python/run_api.py index 93b202f..5ac0bbe 100644 --- a/src/alpine_bits_python/run_api.py +++ b/src/alpine_bits_python/run_api.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -"""Startup script for the Wix Form Handler API -""" +"""Startup script for the Wix Form Handler API.""" import os @@ -10,7 +9,6 @@ if __name__ == "__main__": db_path = "alpinebits.db" # Adjust path if needed if os.path.exists(db_path): os.remove(db_path) - print(f"Deleted database file: {db_path}") uvicorn.run( "alpine_bits_python.api:app", diff --git a/src/alpine_bits_python/schemas.py b/src/alpine_bits_python/schemas.py index 5b76afe..4affec1 100644 --- a/src/alpine_bits_python/schemas.py +++ b/src/alpine_bits_python/schemas.py @@ -10,7 +10,7 @@ from XML generation (xsdata) follows clean architecture principles. """ import hashlib -from datetime import date +from datetime import date, datetime from enum import Enum from pydantic import BaseModel, EmailStr, Field, field_validator, model_validator @@ -43,6 +43,7 @@ class ReservationData(BaseModel): md5_unique_id: str | None = Field(None, min_length=1, max_length=32) start_date: date end_date: date + created_at: datetime = Field(default_factory=datetime.now) num_adults: int = Field(..., ge=1) num_children: int = Field(0, ge=0, le=10) children_ages: list[int] = Field(default_factory=list) @@ -50,13 +51,13 @@ class ReservationData(BaseModel): hotel_name: str | None = Field(None, max_length=200) offer: str | None = Field(None, max_length=500) user_comment: str | None = Field(None, max_length=2000) - fbclid: str | None = Field(None, max_length=100) - gclid: str | None = Field(None, max_length=100) - utm_source: str | None = Field(None, max_length=100) - utm_medium: str | None = Field(None, max_length=100) - utm_campaign: str | None = Field(None, max_length=100) - utm_term: str | None = Field(None, max_length=100) - utm_content: str | None = Field(None, max_length=100) + fbclid: str | None = Field(None, max_length=300) + gclid: str | None = Field(None, max_length=300) + utm_source: str | None = Field(None, max_length=150) + utm_medium: str | None = Field(None, max_length=150) + utm_campaign: str | None = Field(None, max_length=150) + utm_term: str | None = Field(None, max_length=150) + utm_content: str | None = Field(None, max_length=150) @model_validator(mode="after") def ensure_md5(self) -> "ReservationData": diff --git a/src/alpine_bits_python/util/handshake_util.py b/src/alpine_bits_python/util/handshake_util.py deleted file mode 100644 index 121954b..0000000 --- a/src/alpine_bits_python/util/handshake_util.py +++ /dev/null @@ -1,44 +0,0 @@ -from xsdata_pydantic.bindings import XmlParser - -from ..generated.alpinebits import OtaPingRs - - -def main(): - # test parsing a ping request sample - - path = ( - "AlpineBits-HotelData-2024-10/files/samples/Handshake/Handshake-OTA_PingRS.xml" - ) - - with open(path, encoding="utf-8") as f: - xml = f.read() - - # Parse the XML into the request object - - # Test parsing back - - parser = XmlParser() - - parsed_result = parser.from_string(xml, OtaPingRs) - - print(parsed_result.echo_data) - - warning = parsed_result.warnings.warning[0] - - print(warning.type_value) - - print(type(warning.content)) - - print(warning.content[0]) - - # save json in echo_data to file with indents - output_path = "echo_data_response.json" - with open(output_path, "w", encoding="utf-8") as out_f: - import json - - json.dump(json.loads(parsed_result.echo_data), out_f, indent=4) - print(f"Saved echo_data json to {output_path}") - - -if __name__ == "__main__": - main() diff --git a/start_api.py b/start_api.py index 608740a..fff8abd 100644 --- a/start_api.py +++ b/start_api.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -"""Convenience launcher for the Wix Form Handler API -""" +"""Convenience launcher for the Wix Form Handler API.""" import os import subprocess diff --git a/test_handshake.py b/test_handshake.py index 75b33f5..4d7fb15 100644 --- a/test_handshake.py +++ b/test_handshake.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -"""Test the handshake functionality with the real AlpineBits sample file. -""" +"""Test the handshake functionality with the real AlpineBits sample file.""" import asyncio @@ -8,8 +7,6 @@ from alpine_bits_python.alpinebits_server import AlpineBitsServer async def main(): - print("🔄 Testing AlpineBits Handshake with Sample File") - print("=" * 60) # Create server instance server = AlpineBitsServer() @@ -20,15 +17,12 @@ async def main(): ) as f: ping_request_xml = f.read() - print("📤 Sending handshake request...") # Handle the ping request - response = await server.handle_request( + await server.handle_request( "OTA_Ping:Handshaking", ping_request_xml, "2024-10" ) - print(f"\n📥 Response Status: {response.status_code}") - print(f"📄 Response XML:\n{response.xml_content}") if __name__ == "__main__": diff --git a/tests/test_alpine_bits_helper.py b/tests/test_alpine_bits_helper.py index a3f4e0c..da083d2 100644 --- a/tests/test_alpine_bits_helper.py +++ b/tests/test_alpine_bits_helper.py @@ -1,4 +1,3 @@ - import pytest from alpine_bits_python.alpine_bits_helpers import ( diff --git a/tests/test_alpine_bits_server_read.py b/tests/test_alpine_bits_server_read.py index 67cf0db..cd02fbe 100644 --- a/tests/test_alpine_bits_server_read.py +++ b/tests/test_alpine_bits_server_read.py @@ -4,22 +4,28 @@ This module tests the ReadAction handler which retrieves reservations from the database and returns them as OTA_ResRetrieveRS XML. """ +import hashlib from datetime import UTC, date, datetime import pytest +import pytest_asyncio +from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine from xsdata.formats.dataclass.serializers.config import SerializerConfig from xsdata_pydantic.bindings import XmlParser, XmlSerializer from alpine_bits_python.alpine_bits_helpers import create_res_retrieve_response -from alpine_bits_python.alpinebits_server import AlpineBitsClientInfo -from alpine_bits_python.db import Base, Customer, Reservation +from alpine_bits_python.alpinebits_server import AlpineBitsClientInfo, AlpineBitsServer +from alpine_bits_python.db import AckedRequest, Base, Customer, Reservation from alpine_bits_python.generated import OtaReadRq from alpine_bits_python.generated.alpinebits import OtaResRetrieveRs from alpine_bits_python.schemas import ReservationData +# HTTP status code constants +HTTP_OK = 200 -@pytest.fixture + +@pytest_asyncio.fixture async def test_db_engine(): """Create an in-memory SQLite database for testing.""" engine = create_async_engine( @@ -37,7 +43,7 @@ async def test_db_engine(): await engine.dispose() -@pytest.fixture +@pytest_asyncio.fixture async def test_db_session(test_db_engine): """Create a test database session.""" async_session = async_sessionmaker( @@ -85,15 +91,15 @@ def sample_reservation(sample_customer): num_children=1, children_ages=[8], offer="Christmas Special", - created_at=datetime.now(UTC), + created_at=datetime(2024, 11, 1, 12, 0, 0, tzinfo=UTC), utm_source="google", utm_medium="cpc", utm_campaign="winter2024", utm_term="ski resort", utm_content="ad1", user_comment="Late check-in requested", - fbclid="", - gclid="abc123xyz", + fbclid="PAZXh0bgNhZW0BMABhZGlkAasmYBTNE3QBp1jWuJ9zIpfEGRJMP63fMAMI405yvG5EtH-OT0PxSkAbBJaudFHR6cMtkdHu_aem_fopaFtECyVPNW9fmWfEkyA", + gclid="", hotel_code="HOTEL123", hotel_name="Alpine Paradise Resort", ) @@ -103,8 +109,6 @@ def sample_reservation(sample_customer): children_csv = ",".join(str(int(a)) for a in children_list) if children_list else "" data["children_ages"] = children_csv - print(data) - return Reservation( id=1, customer_id=1, @@ -135,7 +139,7 @@ def minimal_reservation(minimal_customer): num_children=0, children_ages=[], hotel_code="HOTEL123", - created_at=datetime.now(UTC), + created_at=datetime(2024, 12, 2, 12, 0, 0, tzinfo=UTC), hotel_name="Alpine Paradise Resort", ) @@ -163,7 +167,7 @@ def read_request_xml(): Version="8.000"> - + """ @@ -187,13 +191,20 @@ def read_request_xml_no_date_filter(): def test_config(): """Test configuration with hotel credentials.""" return { - "hotels": [ + "server": { + "codecontext": "ADVERTISING", + "code": "70597314", + "companyname": "99tales Gmbh", + "res_id_source_context": "99tales", + }, + "alpine_bits_auth": [ { "hotel_id": "HOTEL123", + "hotel_name": "Alpine Paradise Resort", "username": "testuser", "password": "testpass", } - ] + ], } @@ -210,9 +221,9 @@ def client_info(): class TestCreateResRetrieveResponse: """Test the create_res_retrieve_response function.""" - def test_empty_list(self): + def test_empty_list(self, test_config): """Test creating response with empty reservation list.""" - response = create_res_retrieve_response([]) + response = create_res_retrieve_response([], config=test_config) assert response is not None, "Response should not be None" @@ -227,10 +238,10 @@ class TestCreateResRetrieveResponse: "Response should have reservations_list attribute" ) - def test_single_reservation(self, sample_reservation, sample_customer): + def test_single_reservation(self, sample_reservation, sample_customer, test_config): """Test creating response with single reservation.""" reservation_pairs = [(sample_reservation, sample_customer)] - response = create_res_retrieve_response(reservation_pairs) + response = create_res_retrieve_response(reservation_pairs, config=test_config) assert response is not None assert hasattr(response, "reservations_list"), ( @@ -268,13 +279,14 @@ class TestCreateResRetrieveResponse: sample_customer, minimal_reservation, minimal_customer, + test_config, ): """Test creating response with multiple reservations.""" reservation_pairs = [ (sample_reservation, sample_customer), (minimal_reservation, minimal_customer), ] - response = create_res_retrieve_response(reservation_pairs) + response = create_res_retrieve_response(reservation_pairs, config=test_config) assert response is not None @@ -292,13 +304,15 @@ class TestCreateResRetrieveResponse: assert "John" in xml_output assert "Jane" in xml_output - def test_reservation_with_children(self, sample_reservation, sample_customer): + def test_reservation_with_children( + self, sample_reservation, sample_customer, test_config + ): """Test reservation with children ages.""" sample_reservation.num_children = 2 sample_reservation.children_ages = "8,5" reservation_pairs = [(sample_reservation, sample_customer)] - response = create_res_retrieve_response(reservation_pairs) + response = create_res_retrieve_response(reservation_pairs, config=test_config) config = SerializerConfig(pretty_print=True) serializer = XmlSerializer(config=config) @@ -327,7 +341,7 @@ class TestXMLParsing: assert hotel_req.hotel_code == "HOTEL123" assert hotel_req.hotel_name == "Alpine Paradise Resort" assert hotel_req.selection_criteria is not None - assert hotel_req.selection_criteria.start == "2024-12-01" + assert hotel_req.selection_criteria.start == "2024-10-01" def test_parse_read_request_no_date(self, read_request_xml_no_date_filter): """Test parsing of OTA_ReadRQ without date filter.""" @@ -343,10 +357,11 @@ class TestXMLParsing: self, sample_reservation, sample_customer, + test_config, ): """Test serialization of retrieve response to XML.""" reservation_pairs = [(sample_reservation, sample_customer)] - response = create_res_retrieve_response(reservation_pairs) + response = create_res_retrieve_response(reservation_pairs, config=test_config) config = SerializerConfig( pretty_print=True, xml_declaration=True, encoding="UTF-8" @@ -373,7 +388,7 @@ class TestXMLParsing: class TestEdgeCases: """Test edge cases and error conditions.""" - def test_customer_with_special_characters(self): + def test_customer_with_special_characters(self, test_config): """Test customer with special characters in name.""" customer = Customer( id=99, @@ -395,7 +410,7 @@ class TestEdgeCases: ) reservation_pairs = [(reservation, customer)] - response = create_res_retrieve_response(reservation_pairs) + response = create_res_retrieve_response(reservation_pairs, config=test_config) config = SerializerConfig(pretty_print=True, encoding="UTF-8") serializer = XmlSerializer(config=config) @@ -406,7 +421,7 @@ class TestEdgeCases: assert response is not None assert xml_output is not None - def test_reservation_with_all_utm_parameters(self): + def test_reservation_with_all_utm_parameters(self, test_config): """Test reservation with all UTM tracking parameters.""" customer = Customer( id=97, @@ -439,11 +454,11 @@ class TestEdgeCases: ) reservation_pairs = [(reservation_db, customer)] - response = create_res_retrieve_response(reservation_pairs) + response = create_res_retrieve_response(reservation_pairs, config=test_config) config = SerializerConfig(pretty_print=True) serializer = XmlSerializer(config=config) - xml_output = serializer.render( + serializer.render( response, ns_map={None: "http://www.opentravel.org/OTA/2003/05"} ) @@ -451,5 +466,487 @@ class TestEdgeCases: # UTM parameters should be in comments or other fields +class TestAcknowledgments: + """Test acknowledgments. + + 1. Setup AlpineBitsServer so that it can respond to sample read requests. + 2. Send acknowledgment requests and verify responses. + 3. Verify that acknowledgments are recorded in the database. + 4. Verify that Read Requests no longer return already acknowledged reservations. + 5. Verify that that still happens when SelectionCriteria date filters are applied. + + """ + + @pytest_asyncio.fixture + async def populated_db_session( + self, + test_db_session, + sample_reservation, + sample_customer, + minimal_reservation, + minimal_customer, + ): + """Create a database session with sample data.""" + # Add customers + test_db_session.add(sample_customer) + test_db_session.add(minimal_customer) + await test_db_session.commit() + + # Add reservations + test_db_session.add(sample_reservation) + test_db_session.add(minimal_reservation) + await test_db_session.commit() + + return test_db_session + + @pytest.fixture + def alpinebits_server(self, test_config): + """Create AlpineBitsServer instance for testing.""" + return AlpineBitsServer(config=test_config) + + @pytest.fixture + def notif_report_xml_template(self): + """Template for OTA_NotifReportRQ XML request.""" + return """ + + + + + {reservations} + + + +""" + + def create_notif_report_xml(self, unique_ids): + """Create a notification report XML with given unique IDs.""" + template = """ + + + + + {reservations} + + + +""" + + reservations = "" + for unique_id in unique_ids: + reservations += f'' + + return template.format(reservations=reservations) + + @pytest.mark.asyncio + async def test_setup_server_responds_to_read_requests( + self, alpinebits_server, populated_db_session, client_info, read_request_xml + ): + """Test 1: Setup AlpineBitsServer so that it can respond to sample read requests.""" + # Send a read request and verify we get a response + response = await alpinebits_server.handle_request( + request_action_name="OTA_Read:GuestRequests", + request_xml=read_request_xml, + client_info=client_info, + version="2024-10", + dbsession=populated_db_session, + ) + + assert response is not None + assert response.status_code == HTTP_OK + assert response.xml_content is not None + + # Verify response contains reservation data + assert "OTA_ResRetrieveRS" in response.xml_content + assert "HOTEL123" in response.xml_content + + @pytest.mark.asyncio + async def test_send_acknowledgment_and_verify_response( + self, alpinebits_server, populated_db_session, client_info + ): + """Test 2: Send acknowledgment requests and verify responses.""" + # First, get the unique IDs from a read request + read_xml = """ + + + + +""" + + # Get reservations first + _read_response = await alpinebits_server.handle_request( + request_action_name="OTA_Read:GuestRequests", + request_xml=read_xml, + client_info=client_info, + version="2024-10", + dbsession=populated_db_session, + ) + + # Extract unique IDs from the response (we'll use test unique IDs) + test_unique_ids = [ + "RES-2024-001", + "RES-2024-002", + ] # In reality, these would be extracted from read response + + # Create acknowledgment request + notif_report_xml = self.create_notif_report_xml(test_unique_ids) + + # Send acknowledgment + ack_response = await alpinebits_server.handle_request( + request_action_name="OTA_NotifReport:GuestRequests", + request_xml=notif_report_xml, + client_info=client_info, + version="2024-10", + dbsession=populated_db_session, + ) + + assert ack_response is not None + assert ack_response.status_code == HTTP_OK + assert "OTA_NotifReportRS" in ack_response.xml_content + + @pytest.mark.asyncio + async def test_acknowledgments_recorded_in_database( + self, alpinebits_server, populated_db_session, client_info + ): + """Test 3: Verify that acknowledgments are recorded in the database.""" + # Create acknowledgment request + test_unique_ids = ["test-ack-id-1", "test-ack-id-2"] + notif_report_xml = self.create_notif_report_xml(test_unique_ids) + + # Count existing acked requests + result = await populated_db_session.execute(select(AckedRequest)) + initial_count = len(result.all()) + + # Send acknowledgment + await alpinebits_server.handle_request( + request_action_name="OTA_NotifReport:GuestRequests", + request_xml=notif_report_xml, + client_info=client_info, + version="2024-10", + dbsession=populated_db_session, + ) + + # Verify acknowledgments were recorded + result = await populated_db_session.execute(select(AckedRequest)) + acked_requests = result.all() + assert len(acked_requests) == initial_count + 2 + + # Verify the specific acknowledgments + acked_ids = [req[0].unique_id for req in acked_requests] + assert "test-ack-id-1" in acked_ids + assert "test-ack-id-2" in acked_ids + + # Verify client ID is recorded + for req in acked_requests[-2:]: # Last 2 requests + assert req[0].client_id == client_info.client_id + + @pytest.mark.asyncio + async def test_read_excludes_acknowledged_reservations( + self, alpinebits_server, populated_db_session, client_info + ): + """Test 4: Verify that Read Requests no longer return already acknowledged reservations.""" + # First read request - should return all reservations + read_xml = """ + + + + +""" + + initial_response = await alpinebits_server.handle_request( + request_action_name="OTA_Read:GuestRequests", + request_xml=read_xml, + client_info=client_info, + version="2024-10", + dbsession=populated_db_session, + ) + + # Parse response to count initial reservations + parser = XmlParser() + initial_parsed = parser.from_string( + initial_response.xml_content, OtaResRetrieveRs + ) + initial_count = 0 + if ( + initial_parsed.reservations_list + and initial_parsed.reservations_list.hotel_reservation + ): + initial_count = len(initial_parsed.reservations_list.hotel_reservation) + + # Acknowledge one reservation by using its MD5 hash + # Get the unique_id from sample reservation and create its MD5 + sample_unique_id = "RES-2024-001" + md5_hash = hashlib.md5(sample_unique_id.encode()).hexdigest() + + # Manually insert acknowledgment + acked_request = AckedRequest( + unique_id=md5_hash, + client_id=client_info.client_id, + timestamp=datetime.now(UTC), + ) + populated_db_session.add(acked_request) + await populated_db_session.commit() + + # Second read request - should return fewer reservations + second_response = await alpinebits_server.handle_request( + request_action_name="OTA_Read:GuestRequests", + request_xml=read_xml, + client_info=client_info, + version="2024-10", + dbsession=populated_db_session, + ) + + # Parse second response + second_parsed = parser.from_string( + second_response.xml_content, OtaResRetrieveRs + ) + second_count = 0 + if ( + second_parsed.reservations_list + and second_parsed.reservations_list.hotel_reservation + ): + second_count = len(second_parsed.reservations_list.hotel_reservation) + + # Should have one fewer reservation + assert second_count == initial_count - 1 + + @pytest.mark.asyncio + async def test_acknowledgments_work_with_date_filters( + self, + alpinebits_server, + populated_db_session, + client_info, + read_request_xml_no_date_filter, + ): + """Test 5: Verify acknowledgments still work when SelectionCriteria date filters are applied.""" + # Read request with date filter + read_xml_with_date = """ + + + + + + +""" + + # First read with date filter + initial_response = await alpinebits_server.handle_request( + request_action_name="OTA_Read:GuestRequests", + request_xml=read_xml_with_date, + client_info=client_info, + version="2024-10", + dbsession=populated_db_session, + ) + + parser = XmlParser() + initial_parsed = parser.from_string( + initial_response.xml_content, OtaResRetrieveRs + ) + initial_count = 0 + if ( + initial_parsed.reservations_list + and initial_parsed.reservations_list.hotel_reservation + ): + initial_count = len(initial_parsed.reservations_list.hotel_reservation) + + assert initial_count > 0, "Initial count with date filter should be > 0" + assert initial_count == 1, ( + "Should only return one reservation with this date filter" + ) + + # Acknowledge one reservation that falls within the date range + # The sample_reservation was created at 2024-11-01 and thus falls out of range + sample_unique_id = "RES-2024-002" + md5_hash = hashlib.md5(sample_unique_id.encode()).hexdigest() + + acked_request = AckedRequest( + unique_id=md5_hash, + client_id=client_info.client_id, + timestamp=datetime.now(UTC), + ) + populated_db_session.add(acked_request) + await populated_db_session.commit() + + without_filter_read = await alpinebits_server.handle_request( + request_action_name="OTA_Read:GuestRequests", + request_xml=read_request_xml_no_date_filter, + client_info=client_info, + version="2024-10", + dbsession=populated_db_session, + ) + + without_filter_parsed = parser.from_string( + without_filter_read.xml_content, OtaResRetrieveRs + ) + + without_filter_count = 0 + if ( + without_filter_parsed.reservations_list + and without_filter_parsed.reservations_list.hotel_reservation + ): + without_filter_count = len( + without_filter_parsed.reservations_list.hotel_reservation + ) + + assert without_filter_count == 1, ( + "Without date filter, should return one reservation after acknowledgment" + ) + + # Second read with same date filter + second_response = await alpinebits_server.handle_request( + request_action_name="OTA_Read:GuestRequests", + request_xml=read_xml_with_date, + client_info=client_info, + version="2024-10", + dbsession=populated_db_session, + ) + + second_parsed = parser.from_string( + second_response.xml_content, OtaResRetrieveRs + ) + second_count = 0 + if ( + second_parsed.reservations_list + and second_parsed.reservations_list.hotel_reservation + ): + second_count = len(second_parsed.reservations_list.hotel_reservation) + + # Should have exactly the same amount of reservations + assert second_count == initial_count, ( + "Acknowledgment should not affect count when date filter is applied" + ) + + @pytest.mark.asyncio + async def test_same_customer_multiple_reservations( + self, + alpinebits_server, + test_db_session, + client_info, + sample_customer, + ): + """Test same customer with multiple reservations returns all.""" + # Add the customer to the database + test_db_session.add(sample_customer) + await test_db_session.commit() + + # Create two reservations for the same customer + first_reservation = ReservationData( + unique_id="RES-2024-MULTI-001", + start_date=date(2024, 12, 25), + end_date=date(2024, 12, 31), + num_adults=2, + num_children=0, + children_ages=[], + hotel_code="HOTEL123", + hotel_name="Alpine Paradise Resort", + created_at=datetime(2024, 11, 1, 12, 0, 0, tzinfo=UTC), + ) + + second_reservation = ReservationData( + unique_id="RES-2024-MULTI-002", + start_date=date(2025, 3, 15), + end_date=date(2025, 3, 20), + num_adults=2, + num_children=1, + children_ages=[10], + hotel_code="HOTEL123", + hotel_name="Alpine Paradise Resort", + created_at=datetime(2024, 11, 15, 10, 0, 0, tzinfo=UTC), + ) + + # Convert to DB reservations + first_data = first_reservation.model_dump(exclude_none=True) + children_list = first_data.pop("children_ages", []) + children_csv = ( + ",".join(str(int(a)) for a in children_list) if children_list else "" + ) + first_data["children_ages"] = children_csv + + db_first_reservation = Reservation( + id=100, + customer_id=sample_customer.id, + **first_data, + ) + + second_data = second_reservation.model_dump(exclude_none=True) + children_list = second_data.pop("children_ages", []) + children_csv = ( + ",".join(str(int(a)) for a in children_list) if children_list else "" + ) + second_data["children_ages"] = children_csv + + db_second_reservation = Reservation( + id=101, + customer_id=sample_customer.id, + **second_data, + ) + + # Add both reservations to the database + test_db_session.add(db_first_reservation) + test_db_session.add(db_second_reservation) + await test_db_session.commit() + + # Send read request + read_xml = """ + + + + +""" + + response = await alpinebits_server.handle_request( + request_action_name="OTA_Read:GuestRequests", + request_xml=read_xml, + client_info=client_info, + version="2024-10", + dbsession=test_db_session, + ) + + assert response is not None + assert response.status_code == HTTP_OK + + # Parse response to verify both reservations are returned + parser = XmlParser() + parsed_response = parser.from_string(response.xml_content, OtaResRetrieveRs) + + assert parsed_response.reservations_list is not None + assert parsed_response.reservations_list.hotel_reservation is not None + + reservation_count = len(parsed_response.reservations_list.hotel_reservation) + expected_reservations = 2 + assert reservation_count == expected_reservations, ( + "Should return 2 reservations for the same customer" + ) + + # Verify both reservations are present in the response + xml_content = response.xml_content + assert "John" in xml_content # Customer first name + assert "Doe" in xml_content # Customer last name + + # Both reservations should be linked to the same customer + # Verify this by checking that customer appears in both reservation contexts + min_customer_name_occurrences = 2 + assert xml_content.count("John") >= min_customer_name_occurrences, ( + "Customer name should appear for each reservation" + ) + + if __name__ == "__main__": pytest.main([__file__, "-v"]) diff --git a/tests/test_alpinebits_server_ping.py b/tests/test_alpinebits_server_ping.py index 702ba42..3ad8009 100644 --- a/tests/test_alpinebits_server_ping.py +++ b/tests/test_alpinebits_server_ping.py @@ -11,8 +11,7 @@ def extract_relevant_sections(xml_string): # Remove version attribute value, keep only presence # Use the same XmlParser as AlpineBitsServer parser = XmlParser() - obj = parser.from_string(xml_string, OtaPingRs) - return obj + return parser.from_string(xml_string, OtaPingRs) @pytest.mark.asyncio diff --git a/tests/test_api.py b/tests/test_api.py new file mode 100644 index 0000000..1fc75dd --- /dev/null +++ b/tests/test_api.py @@ -0,0 +1,723 @@ +"""Tests for API endpoints using FastAPI TestClient. + +This module tests all FastAPI endpoints including: +- Health check endpoints +- Wix webhook endpoints +- AlpineBits server endpoint +- XML upload endpoint +- Authentication +- Rate limiting +""" + +import base64 +import gzip +import uuid +from pathlib import Path +from unittest.mock import patch + +import pytest +import pytest_asyncio +from fastapi.testclient import TestClient +from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine + +from alpine_bits_python.api import app +from alpine_bits_python.db import Base, Customer, Reservation + + +@pytest_asyncio.fixture +async def test_db_engine(): + """Create an in-memory SQLite database for testing.""" + engine = create_async_engine( + "sqlite+aiosqlite:///:memory:", + echo=False, + ) + + # Create tables + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.create_all) + + yield engine + + # Cleanup + await engine.dispose() + + +@pytest_asyncio.fixture +async def test_db_session(test_db_engine): + """Create a test database session.""" + async_session = async_sessionmaker( + test_db_engine, + class_=AsyncSession, + expire_on_commit=False, + ) + + async with async_session() as session: + yield session + + +@pytest.fixture +def test_config(): + """Test configuration.""" + return { + "server": { + "codecontext": "ADVERTISING", + "code": "70597314", + "companyname": "99tales Gmbh", + "res_id_source_context": "99tales", + }, + "alpine_bits_auth": [ + { + "hotel_id": "HOTEL123", + "hotel_name": "Test Hotel", + "username": "testuser", + "password": "testpass", + } + ], + "default_hotel_code": "HOTEL123", + "default_hotel_name": "Test Hotel", + "database": {"url": "sqlite+aiosqlite:///:memory:"}, + } + + +@pytest.fixture +def client(test_config): + """Create a test client with mocked dependencies. + + Each test gets a fresh TestClient instance to avoid database conflicts. + Mocks load_config to return test_config instead of production config. + """ + # Import locally to avoid circular imports + from alpine_bits_python.alpinebits_server import AlpineBitsServer # noqa: PLC0415 + + # Mock load_config to return test_config instead of production config + with patch("alpine_bits_python.api.load_config", return_value=test_config): + # Create a new in-memory database for each test + engine = create_async_engine( + "sqlite+aiosqlite:///:memory:", + echo=False, + ) + + # Setup app state (will be overridden by lifespan but we set it anyway) + app.state.engine = engine + app.state.async_sessionmaker = async_sessionmaker( + engine, expire_on_commit=False + ) + app.state.config = test_config + app.state.alpine_bits_server = AlpineBitsServer(test_config) + + # TestClient will trigger lifespan events which create the tables + # The mocked load_config will ensure test_config is used + with TestClient(app) as test_client: + yield test_client + + +@pytest.fixture +def sample_wix_form_data(): + """Sample Wix form submission data. + + Each call generates unique IDs to avoid database conflicts. + """ + unique_id = uuid.uuid4().hex[:8] + return { + "data": { + "submissionId": f"test-submission-{unique_id}", + "submissionTime": "2025-10-07T05:48:41.855Z", + "contact": { + "name": {"first": "John", "last": "Doe"}, + "email": f"john.doe.{unique_id}@example.com", + "phones": [{"e164Phone": "+1234567890"}], + "locale": "en-US", + "contactId": f"contact-{unique_id}", + }, + "field:anrede": "Mr.", + "field:form_field_5a7b": "Checked", + "field:date_picker_a7c8": "2024-12-25", + "field:date_picker_7e65": "2024-12-31", + "field:number_7cf5": "2", + "field:anzahl_kinder": "1", + "field:alter_kind_1": "8", + "field:angebot_auswaehlen": "Christmas Special", + "field:utm_source": "google", + "field:utm_medium": "cpc", + "field:utm_campaign": "winter2024", + "field:fbclid": "test_fbclid_123", + "field:long_answer_3524": "Late check-in please", + } + } + + +@pytest.fixture +def basic_auth_headers(): + """Create Basic Auth headers for testing.""" + credentials = base64.b64encode(b"testuser:testpass").decode("utf-8") + return {"Authorization": f"Basic {credentials}"} + + +class TestHealthEndpoints: + """Test health check and root endpoints.""" + + def test_root_endpoint(self, client): + """Test GET / returns health status.""" + response = client.get("/api/") + assert response.status_code == 200 + data = response.json() + assert data["message"] == "Wix Form Handler API is running" + assert "timestamp" in data + assert data["status"] == "healthy" + assert "rate_limits" in data + + def test_health_check_endpoint(self, client): + """Test GET /api/health returns healthy status.""" + response = client.get("/api/health") + assert response.status_code == 200 + data = response.json() + assert data["status"] == "healthy" + assert data["service"] == "wix-form-handler" + assert data["version"] == "1.0.0" + assert "timestamp" in data + + def test_landing_page(self, client): + """Test GET / (landing page) returns HTML.""" + response = client.get("/") + assert response.status_code == 200 + assert "text/html" in response.headers["content-type"] + assert "99tales" in response.text or "Construction" in response.text + + +class TestWixWebhookEndpoint: + """Test Wix form webhook endpoint.""" + + def test_wix_webhook_success(self, client, sample_wix_form_data): + """Test successful Wix form submission.""" + response = client.post("/api/webhook/wix-form", json=sample_wix_form_data) + + assert response.status_code == 200 + data = response.json() + assert data["status"] == "success" + assert "timestamp" in data + assert "data_logged_to" in data + + def test_wix_webhook_creates_customer_and_reservation( + self, client, sample_wix_form_data + ): + """Test that webhook creates customer and reservation in database.""" + response = client.post("/api/webhook/wix-form", json=sample_wix_form_data) + assert response.status_code == 200 + + # Verify data was saved to database + # Use the client's app state engine, not a separate test_db_engine + async def check_db(): + engine = client.app.state.engine + async_session = async_sessionmaker(engine, expire_on_commit=False) + async with async_session() as session: + from sqlalchemy import select + + # Check customer was created + result = await session.execute(select(Customer)) + customers = result.scalars().all() + assert len(customers) == 1 + customer = customers[0] + assert customer.given_name == "John" + assert customer.surname == "Doe" + # Email address in sample_wix_form_data has unique ID appended + assert customer.email_address.startswith("john.doe.") + assert "@example.com" in customer.email_address + + # Check reservation was created + result = await session.execute(select(Reservation)) + reservations = result.scalars().all() + assert len(reservations) == 1 + reservation = reservations[0] + assert reservation.customer_id == customer.id + assert reservation.num_adults == 2 + assert reservation.num_children == 1 + + import asyncio + + asyncio.run(check_db()) + + def test_wix_webhook_minimal_data(self, client): + """Test webhook with minimal required data.""" + minimal_data = { + "data": { + "submissionId": "minimal-123", + "submissionTime": "2025-01-10T12:00:00.000Z", + "contact": { + "name": {"first": "Jane", "last": "Smith"}, + "email": "jane@example.com", + }, + "field:date_picker_a7c8": "2025-01-15", + "field:date_picker_7e65": "2025-01-20", + } + } + + response = client.post("/api/webhook/wix-form", json=minimal_data) + assert response.status_code == 200 + data = response.json() + assert data["status"] == "success" + + def test_wix_webhook_test_endpoint(self, client, sample_wix_form_data): + """Test the test endpoint works identically.""" + response = client.post("/api/webhook/wix-form/test", json=sample_wix_form_data) + assert response.status_code == 200 + data = response.json() + assert data["status"] == "success" + + def test_wix_webhook_updates_existing_customer(self, client): + """Test that same contact_id updates customer instead of duplicate.""" + # First submission + first_submission = { + "data": { + "submissionId": "test-submission-001", + "submissionTime": "2025-10-07T05:48:41.855Z", + "contact": { + "name": {"first": "John", "last": "Doe"}, + "email": "john.doe@example.com", + "phones": [{"e164Phone": "+1234567890"}], + "locale": "en-US", + "contactId": "fixed-contact-id-123", + }, + "field:anrede": "Mr.", + "field:date_picker_a7c8": "2024-12-25", + "field:date_picker_7e65": "2024-12-31", + "field:number_7cf5": "2", + "field:anzahl_kinder": "0", + } + } + + response = client.post("/api/webhook/wix-form", json=first_submission) + assert response.status_code == 200 + + # Second submission with same contact_id but different data + second_submission = { + "data": { + "submissionId": "test-submission-002", + "submissionTime": "2025-10-08T10:30:00.000Z", + "contact": { + "name": {"first": "John", "last": "Smith"}, # Changed last name + "email": "john.smith@example.com", # Changed email + "phones": [{"e164Phone": "+9876543210"}], # Changed phone + "locale": "de-DE", # Changed locale + "contactId": "fixed-contact-id-123", # Same contact_id + }, + "field:anrede": "Dr.", # Changed prefix + "field:date_picker_a7c8": "2025-01-10", + "field:date_picker_7e65": "2025-01-15", + "field:number_7cf5": "4", + "field:anzahl_kinder": "2", + "field:alter_kind_1": "5", + "field:alter_kind_2": "10", + } + } + + response = client.post("/api/webhook/wix-form", json=second_submission) + assert response.status_code == 200 + + # Verify only one customer exists with updated information + async def check_db(): + from sqlalchemy import select # noqa: PLC0415 + + engine = client.app.state.engine + async_session = async_sessionmaker(engine, expire_on_commit=False) + async with async_session() as session: + + # Check only one customer exists + result = await session.execute(select(Customer)) + customers = result.scalars().all() + assert len(customers) == 1, "Should have exactly one customer" + + customer = customers[0] + # Verify customer was updated with new information + assert customer.given_name == "John" + assert customer.surname == "Smith", "Last name updated" + assert ( + customer.email_address == "john.smith@example.com" + ), "Email updated" + assert customer.phone == "+9876543210", "Phone updated" + assert customer.name_prefix == "Dr.", "Prefix updated" + assert customer.language == "de", "Language updated" + assert customer.contact_id == "fixed-contact-id-123" + + # Check both reservations were created + result = await session.execute(select(Reservation)) + reservations = result.scalars().all() + expected_reservations = 2 + assert len(reservations) == expected_reservations + # Both reservations should be linked to the same customer + assert all(r.customer_id == customer.id for r in reservations) + + import asyncio # noqa: PLC0415 + + asyncio.run(check_db()) + + +class TestGenericWebhookEndpoint: + """Test generic webhook endpoint.""" + + def test_generic_webhook_success(self, client): + """Test successful generic webhook submission.""" + test_data = { + "event_type": "test_event", + "data": { + "key1": "value1", + "key2": "value2", + "nested": {"foo": "bar"}, + }, + "metadata": {"source": "test_system"}, + } + + response = client.post("/api/webhook/generic", json=test_data) + + assert response.status_code == 200 + data = response.json() + assert data["status"] == "success" + assert "timestamp" in data + assert "data_logged_to" in data + assert "generic_webhooks" in data["data_logged_to"] + assert data["note"] == "Data logged for later analysis" + + def test_generic_webhook_empty_payload(self, client): + """Test generic webhook with empty payload.""" + response = client.post("/api/webhook/generic", json={}) + + assert response.status_code == 200 + data = response.json() + assert data["status"] == "success" + + def test_generic_webhook_complex_nested_data(self, client): + """Test generic webhook with complex nested data structures.""" + complex_data = { + "arrays": [1, 2, 3], + "nested": {"level1": {"level2": {"level3": "deep"}}}, + "mixed": [{"a": 1}, {"b": 2}], + } + + response = client.post("/api/webhook/generic", json=complex_data) + + assert response.status_code == 200 + data = response.json() + assert data["status"] == "success" + + +class TestAlpineBitsServerEndpoint: + """Test AlpineBits server endpoint.""" + + def test_alpinebits_handshake_ping_success(self, client, basic_auth_headers): + """Test AlpineBits handshake with OTA_Ping action using real test data.""" + # Use the actual test data file with proper AlpineBits handshake format + with Path("tests/test_data/Handshake-OTA_PingRQ.xml").open( + encoding="utf-8" + ) as f: + ping_xml = f.read() + + # Prepare multipart form data + form_data = {"action": "OTA_Ping:Handshaking", "request": ping_xml} + + headers = { + **basic_auth_headers, + "X-AlpineBits-ClientProtocolVersion": "2024-10", + "X-AlpineBits-ClientID": "TEST-CLIENT-001", + } + + response = client.post( + "/api/alpinebits/server-2024-10", + data=form_data, + headers=headers, + ) + + assert response.status_code == 200 + assert "OTA_PingRS" in response.text + assert "application/xml" in response.headers["content-type"] + assert "X-AlpineBits-Server-Version" in response.headers + + def test_alpinebits_missing_auth(self, client): + """Test AlpineBits endpoint without authentication.""" + form_data = {"action": "OTA_Ping:Handshaking", "request": ""} + + response = client.post("/api/alpinebits/server-2024-10", data=form_data) + + assert response.status_code == 401 + + def test_alpinebits_invalid_credentials(self, client): + """Test AlpineBits endpoint with invalid credentials.""" + credentials = base64.b64encode(b"wrong:credentials").decode("utf-8") + headers = {"Authorization": f"Basic {credentials}"} + + form_data = {"action": "OTA_Ping:Handshaking", "request": ""} + + response = client.post( + "/api/alpinebits/server-2024-10", data=form_data, headers=headers + ) + + assert response.status_code == 401 + + def test_alpinebits_missing_action(self, client, basic_auth_headers): + """Test AlpineBits endpoint without action parameter.""" + headers = { + **basic_auth_headers, + "X-AlpineBits-ClientProtocolVersion": "2024-10", + } + + form_data = {"request": ""} + + response = client.post( + "/api/alpinebits/server-2024-10", data=form_data, headers=headers + ) + + assert response.status_code == 400 + + def test_alpinebits_gzip_compression(self, client, basic_auth_headers): + """Test AlpineBits endpoint with gzip compressed request.""" + # Use real test data + with open("tests/test_data/Handshake-OTA_PingRQ.xml", encoding="utf-8") as f: + ping_xml = f.read() + + form_data = f"action=OTA_Ping:Handshaking&request={ping_xml}" + compressed_data = gzip.compress(form_data.encode("utf-8")) + + headers = { + **basic_auth_headers, + "X-AlpineBits-ClientProtocolVersion": "2024-10", + "Content-Encoding": "gzip", + "Content-Type": "application/x-www-form-urlencoded", + } + + response = client.post( + "/api/alpinebits/server-2024-10", + content=compressed_data, + headers=headers, + ) + + assert response.status_code == 200 + assert "OTA_PingRS" in response.text + + +class TestXMLUploadEndpoint: + """Test XML upload endpoint for conversions.""" + + def test_xml_upload_success(self, client, basic_auth_headers): + """Test successful XML upload.""" + xml_content = """ + + + + + + +""" + + response = client.put( + "/api/hoteldata/conversions_import/test_reservation.xml", + content=xml_content.encode("utf-8"), + headers={**basic_auth_headers, "Content-Type": "application/xml"}, + ) + + assert response.status_code == 200 + assert "Xml received" in response.text + + def test_xml_upload_gzip_compressed(self, client, basic_auth_headers): + """Test XML upload with gzip compression.""" + xml_content = """ + + +""" + + compressed = gzip.compress(xml_content.encode("utf-8")) + + headers = { + **basic_auth_headers, + "Content-Type": "application/xml", + "Content-Encoding": "gzip", + } + + response = client.put( + "/api/hoteldata/conversions_import/compressed.xml", + content=compressed, + headers=headers, + ) + + assert response.status_code == 200 + + def test_xml_upload_missing_auth(self, client): + """Test XML upload without authentication.""" + response = client.put( + "/api/hoteldata/conversions_import/test.xml", + content=b"", + ) + + assert response.status_code == 401 + + def test_xml_upload_invalid_path(self, client, basic_auth_headers): + """Test XML upload with path traversal attempt. + + Path traversal is blocked by the server, resulting in 404 Not Found. + """ + response = client.put( + "/api/hoteldata/conversions_import/../../../etc/passwd", + content=b"", + headers=basic_auth_headers, + ) + + # Path traversal results in 404 as the normalized path doesn't match the route + assert response.status_code == 404 + + def test_xml_upload_empty_content(self, client, basic_auth_headers): + """Test XML upload with empty content.""" + response = client.put( + "/api/hoteldata/conversions_import/empty.xml", + content=b"", + headers=basic_auth_headers, + ) + + assert response.status_code == 400 + + def test_xml_upload_non_xml_content(self, client, basic_auth_headers): + """Test XML upload with non-XML content.""" + response = client.put( + "/api/hoteldata/conversions_import/notxml.xml", + content=b"This is not XML content", + headers=basic_auth_headers, + ) + + assert response.status_code == 400 + + +class TestAuthentication: + """Test authentication and authorization.""" + + def test_basic_auth_success(self, client): + """Test successful basic authentication.""" + credentials = base64.b64encode(b"testuser:testpass").decode("utf-8") + headers = {"Authorization": f"Basic {credentials}"} + + form_data = {"action": "OTA_Ping:Handshaking", "request": ""} + + response = client.post( + "/api/alpinebits/server-2024-10", + data=form_data, + headers={ + **headers, + "X-AlpineBits-ClientProtocolVersion": "2024-10", + }, + ) + + # Should not be 401 + assert response.status_code != 401 + + def test_basic_auth_missing_credentials(self, client): + """Test basic auth with missing credentials.""" + response = client.post( + "/api/alpinebits/server-2024-10", + data={"action": "OTA_Ping:Handshaking"}, + ) + + assert response.status_code == 401 + + def test_basic_auth_malformed_header(self, client): + """Test basic auth with malformed Authorization header.""" + headers = {"Authorization": "Basic malformed"} + + response = client.post( + "/api/alpinebits/server-2024-10", + data={"action": "OTA_Ping:Handshaking"}, + headers=headers, + ) + + # FastAPI should handle this gracefully + assert response.status_code in [401, 422] + + +class TestEventDispatcher: + """Test event dispatcher and push notifications.""" + + def test_form_submission_triggers_event( + self, client, sample_wix_form_data + ): + """Test that form submission triggers event dispatcher.""" + # Just verify the endpoint works with the event dispatcher + # The async task runs in background and doesn't affect response + response = client.post("/api/webhook/wix-form", json=sample_wix_form_data) + + assert response.status_code == 200 + # Event dispatcher is tested separately in its own test suite + + +class TestErrorHandling: + """Test error handling across endpoints.""" + + def test_wix_webhook_invalid_json(self, client): + """Test webhook with invalid JSON.""" + response = client.post( + "/api/webhook/wix-form", + content=b"invalid json {{{", + headers={"Content-Type": "application/json"}, + ) + + assert response.status_code == 422 + + def test_wix_webhook_missing_required_fields(self, client): + """Test webhook with missing required fields.""" + invalid_data = {"data": {}} + + response = client.post("/api/webhook/wix-form", json=invalid_data) + + # Should handle gracefully - may be 500 or 400 depending on validation + assert response.status_code in [400, 500] + + def test_alpinebits_invalid_xml(self, client, basic_auth_headers): + """Test AlpineBits endpoint with invalid XML.""" + form_data = { + "action": "OTA_Ping:Handshaking", + "request": "<>", + } + + headers = { + **basic_auth_headers, + "X-AlpineBits-ClientProtocolVersion": "2024-10", + } + + response = client.post( + "/api/alpinebits/server-2024-10", + data=form_data, + headers=headers, + ) + + # Should return error response + assert response.status_code in [400, 500] + + +class TestCORS: + """Test CORS configuration.""" + + def test_cors_preflight_request(self, client): + """Test CORS preflight request.""" + response = client.options( + "/api/health", + headers={ + "Origin": "https://example.wix.com", + "Access-Control-Request-Method": "POST", + }, + ) + + # TestClient returns 400 for OPTIONS requests + # In production, CORS middleware handles preflight correctly + assert response.status_code in [200, 400, 405] + + +class TestRateLimiting: + """Test rate limiting (requires actual rate limiter to be active).""" + + def test_health_endpoint_rate_limit(self, client): + """Test that health endpoint has rate limiting configured.""" + # Make multiple requests + responses = [] + for _ in range(5): + response = client.get("/api/health") + responses.append(response.status_code) + + # All should succeed if under limit + assert all(status == 200 for status in responses) + + +if __name__ == "__main__": + pytest.main([__file__, "-v"]) diff --git a/uv.lock b/uv.lock index d63a246..5fca42f 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.13" [[package]] @@ -39,6 +39,11 @@ dependencies = [ { name = "xsdata-pydantic", extra = ["cli", "lxml", "soap"] }, ] +[package.dev-dependencies] +dev = [ + { name = "pytest-cov" }, +] + [package.metadata] requires-dist = [ { name = "aiosqlite", specifier = ">=0.21.0" }, @@ -61,6 +66,9 @@ requires-dist = [ { name = "xsdata-pydantic", extras = ["cli", "lxml", "soap"], specifier = ">=24.5" }, ] +[package.metadata.requires-dev] +dev = [{ name = "pytest-cov", specifier = ">=7.0.0" }] + [[package]] name = "annotated-types" version = "0.7.0" @@ -196,6 +204,67 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] +[[package]] +name = "coverage" +version = "7.10.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/51/26/d22c300112504f5f9a9fd2297ce33c35f3d353e4aeb987c8419453b2a7c2/coverage-7.10.7.tar.gz", hash = "sha256:f4ab143ab113be368a3e9b795f9cd7906c5ef407d6173fe9675a902e1fffc239", size = 827704, upload-time = "2025-09-21T20:03:56.815Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/94/b765c1abcb613d103b64fcf10395f54d69b0ef8be6a0dd9c524384892cc7/coverage-7.10.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:981a651f543f2854abd3b5fcb3263aac581b18209be49863ba575de6edf4c14d", size = 218320, upload-time = "2025-09-21T20:01:56.629Z" }, + { url = "https://files.pythonhosted.org/packages/72/4f/732fff31c119bb73b35236dd333030f32c4bfe909f445b423e6c7594f9a2/coverage-7.10.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:73ab1601f84dc804f7812dc297e93cd99381162da39c47040a827d4e8dafe63b", size = 218575, upload-time = "2025-09-21T20:01:58.203Z" }, + { url = "https://files.pythonhosted.org/packages/87/02/ae7e0af4b674be47566707777db1aa375474f02a1d64b9323e5813a6cdd5/coverage-7.10.7-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a8b6f03672aa6734e700bbcd65ff050fd19cddfec4b031cc8cf1c6967de5a68e", size = 249568, upload-time = "2025-09-21T20:01:59.748Z" }, + { url = "https://files.pythonhosted.org/packages/a2/77/8c6d22bf61921a59bce5471c2f1f7ac30cd4ac50aadde72b8c48d5727902/coverage-7.10.7-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10b6ba00ab1132a0ce4428ff68cf50a25efd6840a42cdf4239c9b99aad83be8b", size = 252174, upload-time = "2025-09-21T20:02:01.192Z" }, + { url = "https://files.pythonhosted.org/packages/b1/20/b6ea4f69bbb52dac0aebd62157ba6a9dddbfe664f5af8122dac296c3ee15/coverage-7.10.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c79124f70465a150e89340de5963f936ee97097d2ef76c869708c4248c63ca49", size = 253447, upload-time = "2025-09-21T20:02:02.701Z" }, + { url = "https://files.pythonhosted.org/packages/f9/28/4831523ba483a7f90f7b259d2018fef02cb4d5b90bc7c1505d6e5a84883c/coverage-7.10.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:69212fbccdbd5b0e39eac4067e20a4a5256609e209547d86f740d68ad4f04911", size = 249779, upload-time = "2025-09-21T20:02:04.185Z" }, + { url = "https://files.pythonhosted.org/packages/a7/9f/4331142bc98c10ca6436d2d620c3e165f31e6c58d43479985afce6f3191c/coverage-7.10.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7ea7c6c9d0d286d04ed3541747e6597cbe4971f22648b68248f7ddcd329207f0", size = 251604, upload-time = "2025-09-21T20:02:06.034Z" }, + { url = "https://files.pythonhosted.org/packages/ce/60/bda83b96602036b77ecf34e6393a3836365481b69f7ed7079ab85048202b/coverage-7.10.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b9be91986841a75042b3e3243d0b3cb0b2434252b977baaf0cd56e960fe1e46f", size = 249497, upload-time = "2025-09-21T20:02:07.619Z" }, + { url = "https://files.pythonhosted.org/packages/5f/af/152633ff35b2af63977edd835d8e6430f0caef27d171edf2fc76c270ef31/coverage-7.10.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:b281d5eca50189325cfe1f365fafade89b14b4a78d9b40b05ddd1fc7d2a10a9c", size = 249350, upload-time = "2025-09-21T20:02:10.34Z" }, + { url = "https://files.pythonhosted.org/packages/9d/71/d92105d122bd21cebba877228990e1646d862e34a98bb3374d3fece5a794/coverage-7.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:99e4aa63097ab1118e75a848a28e40d68b08a5e19ce587891ab7fd04475e780f", size = 251111, upload-time = "2025-09-21T20:02:12.122Z" }, + { url = "https://files.pythonhosted.org/packages/a2/9e/9fdb08f4bf476c912f0c3ca292e019aab6712c93c9344a1653986c3fd305/coverage-7.10.7-cp313-cp313-win32.whl", hash = "sha256:dc7c389dce432500273eaf48f410b37886be9208b2dd5710aaf7c57fd442c698", size = 220746, upload-time = "2025-09-21T20:02:13.919Z" }, + { url = "https://files.pythonhosted.org/packages/b1/b1/a75fd25df44eab52d1931e89980d1ada46824c7a3210be0d3c88a44aaa99/coverage-7.10.7-cp313-cp313-win_amd64.whl", hash = "sha256:cac0fdca17b036af3881a9d2729a850b76553f3f716ccb0360ad4dbc06b3b843", size = 221541, upload-time = "2025-09-21T20:02:15.57Z" }, + { url = "https://files.pythonhosted.org/packages/14/3a/d720d7c989562a6e9a14b2c9f5f2876bdb38e9367126d118495b89c99c37/coverage-7.10.7-cp313-cp313-win_arm64.whl", hash = "sha256:4b6f236edf6e2f9ae8fcd1332da4e791c1b6ba0dc16a2dc94590ceccb482e546", size = 220170, upload-time = "2025-09-21T20:02:17.395Z" }, + { url = "https://files.pythonhosted.org/packages/bb/22/e04514bf2a735d8b0add31d2b4ab636fc02370730787c576bb995390d2d5/coverage-7.10.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a0ec07fd264d0745ee396b666d47cef20875f4ff2375d7c4f58235886cc1ef0c", size = 219029, upload-time = "2025-09-21T20:02:18.936Z" }, + { url = "https://files.pythonhosted.org/packages/11/0b/91128e099035ece15da3445d9015e4b4153a6059403452d324cbb0a575fa/coverage-7.10.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd5e856ebb7bfb7672b0086846db5afb4567a7b9714b8a0ebafd211ec7ce6a15", size = 219259, upload-time = "2025-09-21T20:02:20.44Z" }, + { url = "https://files.pythonhosted.org/packages/8b/51/66420081e72801536a091a0c8f8c1f88a5c4bf7b9b1bdc6222c7afe6dc9b/coverage-7.10.7-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f57b2a3c8353d3e04acf75b3fed57ba41f5c0646bbf1d10c7c282291c97936b4", size = 260592, upload-time = "2025-09-21T20:02:22.313Z" }, + { url = "https://files.pythonhosted.org/packages/5d/22/9b8d458c2881b22df3db5bb3e7369e63d527d986decb6c11a591ba2364f7/coverage-7.10.7-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1ef2319dd15a0b009667301a3f84452a4dc6fddfd06b0c5c53ea472d3989fbf0", size = 262768, upload-time = "2025-09-21T20:02:24.287Z" }, + { url = "https://files.pythonhosted.org/packages/f7/08/16bee2c433e60913c610ea200b276e8eeef084b0d200bdcff69920bd5828/coverage-7.10.7-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:83082a57783239717ceb0ad584de3c69cf581b2a95ed6bf81ea66034f00401c0", size = 264995, upload-time = "2025-09-21T20:02:26.133Z" }, + { url = "https://files.pythonhosted.org/packages/20/9d/e53eb9771d154859b084b90201e5221bca7674ba449a17c101a5031d4054/coverage-7.10.7-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:50aa94fb1fb9a397eaa19c0d5ec15a5edd03a47bf1a3a6111a16b36e190cff65", size = 259546, upload-time = "2025-09-21T20:02:27.716Z" }, + { url = "https://files.pythonhosted.org/packages/ad/b0/69bc7050f8d4e56a89fb550a1577d5d0d1db2278106f6f626464067b3817/coverage-7.10.7-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2120043f147bebb41c85b97ac45dd173595ff14f2a584f2963891cbcc3091541", size = 262544, upload-time = "2025-09-21T20:02:29.216Z" }, + { url = "https://files.pythonhosted.org/packages/ef/4b/2514b060dbd1bc0aaf23b852c14bb5818f244c664cb16517feff6bb3a5ab/coverage-7.10.7-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2fafd773231dd0378fdba66d339f84904a8e57a262f583530f4f156ab83863e6", size = 260308, upload-time = "2025-09-21T20:02:31.226Z" }, + { url = "https://files.pythonhosted.org/packages/54/78/7ba2175007c246d75e496f64c06e94122bdb914790a1285d627a918bd271/coverage-7.10.7-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:0b944ee8459f515f28b851728ad224fa2d068f1513ef6b7ff1efafeb2185f999", size = 258920, upload-time = "2025-09-21T20:02:32.823Z" }, + { url = "https://files.pythonhosted.org/packages/c0/b3/fac9f7abbc841409b9a410309d73bfa6cfb2e51c3fada738cb607ce174f8/coverage-7.10.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4b583b97ab2e3efe1b3e75248a9b333bd3f8b0b1b8e5b45578e05e5850dfb2c2", size = 261434, upload-time = "2025-09-21T20:02:34.86Z" }, + { url = "https://files.pythonhosted.org/packages/ee/51/a03bec00d37faaa891b3ff7387192cef20f01604e5283a5fabc95346befa/coverage-7.10.7-cp313-cp313t-win32.whl", hash = "sha256:2a78cd46550081a7909b3329e2266204d584866e8d97b898cd7fb5ac8d888b1a", size = 221403, upload-time = "2025-09-21T20:02:37.034Z" }, + { url = "https://files.pythonhosted.org/packages/53/22/3cf25d614e64bf6d8e59c7c669b20d6d940bb337bdee5900b9ca41c820bb/coverage-7.10.7-cp313-cp313t-win_amd64.whl", hash = "sha256:33a5e6396ab684cb43dc7befa386258acb2d7fae7f67330ebb85ba4ea27938eb", size = 222469, upload-time = "2025-09-21T20:02:39.011Z" }, + { url = "https://files.pythonhosted.org/packages/49/a1/00164f6d30d8a01c3c9c48418a7a5be394de5349b421b9ee019f380df2a0/coverage-7.10.7-cp313-cp313t-win_arm64.whl", hash = "sha256:86b0e7308289ddde73d863b7683f596d8d21c7d8664ce1dee061d0bcf3fbb4bb", size = 220731, upload-time = "2025-09-21T20:02:40.939Z" }, + { url = "https://files.pythonhosted.org/packages/23/9c/5844ab4ca6a4dd97a1850e030a15ec7d292b5c5cb93082979225126e35dd/coverage-7.10.7-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b06f260b16ead11643a5a9f955bd4b5fd76c1a4c6796aeade8520095b75de520", size = 218302, upload-time = "2025-09-21T20:02:42.527Z" }, + { url = "https://files.pythonhosted.org/packages/f0/89/673f6514b0961d1f0e20ddc242e9342f6da21eaba3489901b565c0689f34/coverage-7.10.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:212f8f2e0612778f09c55dd4872cb1f64a1f2b074393d139278ce902064d5b32", size = 218578, upload-time = "2025-09-21T20:02:44.468Z" }, + { url = "https://files.pythonhosted.org/packages/05/e8/261cae479e85232828fb17ad536765c88dd818c8470aca690b0ac6feeaa3/coverage-7.10.7-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3445258bcded7d4aa630ab8296dea4d3f15a255588dd535f980c193ab6b95f3f", size = 249629, upload-time = "2025-09-21T20:02:46.503Z" }, + { url = "https://files.pythonhosted.org/packages/82/62/14ed6546d0207e6eda876434e3e8475a3e9adbe32110ce896c9e0c06bb9a/coverage-7.10.7-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bb45474711ba385c46a0bfe696c695a929ae69ac636cda8f532be9e8c93d720a", size = 252162, upload-time = "2025-09-21T20:02:48.689Z" }, + { url = "https://files.pythonhosted.org/packages/ff/49/07f00db9ac6478e4358165a08fb41b469a1b053212e8a00cb02f0d27a05f/coverage-7.10.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:813922f35bd800dca9994c5971883cbc0d291128a5de6b167c7aa697fcf59360", size = 253517, upload-time = "2025-09-21T20:02:50.31Z" }, + { url = "https://files.pythonhosted.org/packages/a2/59/c5201c62dbf165dfbc91460f6dbbaa85a8b82cfa6131ac45d6c1bfb52deb/coverage-7.10.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:93c1b03552081b2a4423091d6fb3787265b8f86af404cff98d1b5342713bdd69", size = 249632, upload-time = "2025-09-21T20:02:51.971Z" }, + { url = "https://files.pythonhosted.org/packages/07/ae/5920097195291a51fb00b3a70b9bbd2edbfe3c84876a1762bd1ef1565ebc/coverage-7.10.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:cc87dd1b6eaf0b848eebb1c86469b9f72a1891cb42ac7adcfbce75eadb13dd14", size = 251520, upload-time = "2025-09-21T20:02:53.858Z" }, + { url = "https://files.pythonhosted.org/packages/b9/3c/a815dde77a2981f5743a60b63df31cb322c944843e57dbd579326625a413/coverage-7.10.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:39508ffda4f343c35f3236fe8d1a6634a51f4581226a1262769d7f970e73bffe", size = 249455, upload-time = "2025-09-21T20:02:55.807Z" }, + { url = "https://files.pythonhosted.org/packages/aa/99/f5cdd8421ea656abefb6c0ce92556709db2265c41e8f9fc6c8ae0f7824c9/coverage-7.10.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:925a1edf3d810537c5a3abe78ec5530160c5f9a26b1f4270b40e62cc79304a1e", size = 249287, upload-time = "2025-09-21T20:02:57.784Z" }, + { url = "https://files.pythonhosted.org/packages/c3/7a/e9a2da6a1fc5d007dd51fca083a663ab930a8c4d149c087732a5dbaa0029/coverage-7.10.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2c8b9a0636f94c43cd3576811e05b89aa9bc2d0a85137affc544ae5cb0e4bfbd", size = 250946, upload-time = "2025-09-21T20:02:59.431Z" }, + { url = "https://files.pythonhosted.org/packages/ef/5b/0b5799aa30380a949005a353715095d6d1da81927d6dbed5def2200a4e25/coverage-7.10.7-cp314-cp314-win32.whl", hash = "sha256:b7b8288eb7cdd268b0304632da8cb0bb93fadcfec2fe5712f7b9cc8f4d487be2", size = 221009, upload-time = "2025-09-21T20:03:01.324Z" }, + { url = "https://files.pythonhosted.org/packages/da/b0/e802fbb6eb746de006490abc9bb554b708918b6774b722bb3a0e6aa1b7de/coverage-7.10.7-cp314-cp314-win_amd64.whl", hash = "sha256:1ca6db7c8807fb9e755d0379ccc39017ce0a84dcd26d14b5a03b78563776f681", size = 221804, upload-time = "2025-09-21T20:03:03.4Z" }, + { url = "https://files.pythonhosted.org/packages/9e/e8/71d0c8e374e31f39e3389bb0bd19e527d46f00ea8571ec7ec8fd261d8b44/coverage-7.10.7-cp314-cp314-win_arm64.whl", hash = "sha256:097c1591f5af4496226d5783d036bf6fd6cd0cbc132e071b33861de756efb880", size = 220384, upload-time = "2025-09-21T20:03:05.111Z" }, + { url = "https://files.pythonhosted.org/packages/62/09/9a5608d319fa3eba7a2019addeacb8c746fb50872b57a724c9f79f146969/coverage-7.10.7-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a62c6ef0d50e6de320c270ff91d9dd0a05e7250cac2a800b7784bae474506e63", size = 219047, upload-time = "2025-09-21T20:03:06.795Z" }, + { url = "https://files.pythonhosted.org/packages/f5/6f/f58d46f33db9f2e3647b2d0764704548c184e6f5e014bef528b7f979ef84/coverage-7.10.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9fa6e4dd51fe15d8738708a973470f67a855ca50002294852e9571cdbd9433f2", size = 219266, upload-time = "2025-09-21T20:03:08.495Z" }, + { url = "https://files.pythonhosted.org/packages/74/5c/183ffc817ba68e0b443b8c934c8795553eb0c14573813415bd59941ee165/coverage-7.10.7-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8fb190658865565c549b6b4706856d6a7b09302c797eb2cf8e7fe9dabb043f0d", size = 260767, upload-time = "2025-09-21T20:03:10.172Z" }, + { url = "https://files.pythonhosted.org/packages/0f/48/71a8abe9c1ad7e97548835e3cc1adbf361e743e9d60310c5f75c9e7bf847/coverage-7.10.7-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:affef7c76a9ef259187ef31599a9260330e0335a3011732c4b9effa01e1cd6e0", size = 262931, upload-time = "2025-09-21T20:03:11.861Z" }, + { url = "https://files.pythonhosted.org/packages/84/fd/193a8fb132acfc0a901f72020e54be5e48021e1575bb327d8ee1097a28fd/coverage-7.10.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e16e07d85ca0cf8bafe5f5d23a0b850064e8e945d5677492b06bbe6f09cc699", size = 265186, upload-time = "2025-09-21T20:03:13.539Z" }, + { url = "https://files.pythonhosted.org/packages/b1/8f/74ecc30607dd95ad50e3034221113ccb1c6d4e8085cc761134782995daae/coverage-7.10.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:03ffc58aacdf65d2a82bbeb1ffe4d01ead4017a21bfd0454983b88ca73af94b9", size = 259470, upload-time = "2025-09-21T20:03:15.584Z" }, + { url = "https://files.pythonhosted.org/packages/0f/55/79ff53a769f20d71b07023ea115c9167c0bb56f281320520cf64c5298a96/coverage-7.10.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1b4fd784344d4e52647fd7857b2af5b3fbe6c239b0b5fa63e94eb67320770e0f", size = 262626, upload-time = "2025-09-21T20:03:17.673Z" }, + { url = "https://files.pythonhosted.org/packages/88/e2/dac66c140009b61ac3fc13af673a574b00c16efdf04f9b5c740703e953c0/coverage-7.10.7-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0ebbaddb2c19b71912c6f2518e791aa8b9f054985a0769bdb3a53ebbc765c6a1", size = 260386, upload-time = "2025-09-21T20:03:19.36Z" }, + { url = "https://files.pythonhosted.org/packages/a2/f1/f48f645e3f33bb9ca8a496bc4a9671b52f2f353146233ebd7c1df6160440/coverage-7.10.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:a2d9a3b260cc1d1dbdb1c582e63ddcf5363426a1a68faa0f5da28d8ee3c722a0", size = 258852, upload-time = "2025-09-21T20:03:21.007Z" }, + { url = "https://files.pythonhosted.org/packages/bb/3b/8442618972c51a7affeead957995cfa8323c0c9bcf8fa5a027421f720ff4/coverage-7.10.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a3cc8638b2480865eaa3926d192e64ce6c51e3d29c849e09d5b4ad95efae5399", size = 261534, upload-time = "2025-09-21T20:03:23.12Z" }, + { url = "https://files.pythonhosted.org/packages/b2/dc/101f3fa3a45146db0cb03f5b4376e24c0aac818309da23e2de0c75295a91/coverage-7.10.7-cp314-cp314t-win32.whl", hash = "sha256:67f8c5cbcd3deb7a60b3345dffc89a961a484ed0af1f6f73de91705cc6e31235", size = 221784, upload-time = "2025-09-21T20:03:24.769Z" }, + { url = "https://files.pythonhosted.org/packages/4c/a1/74c51803fc70a8a40d7346660379e144be772bab4ac7bb6e6b905152345c/coverage-7.10.7-cp314-cp314t-win_amd64.whl", hash = "sha256:e1ed71194ef6dea7ed2d5cb5f7243d4bcd334bfb63e59878519be558078f848d", size = 222905, upload-time = "2025-09-21T20:03:26.93Z" }, + { url = "https://files.pythonhosted.org/packages/12/65/f116a6d2127df30bcafbceef0302d8a64ba87488bf6f73a6d8eebf060873/coverage-7.10.7-cp314-cp314t-win_arm64.whl", hash = "sha256:7fe650342addd8524ca63d77b2362b02345e5f1a093266787d210c70a50b471a", size = 220922, upload-time = "2025-09-21T20:03:28.672Z" }, + { url = "https://files.pythonhosted.org/packages/ec/16/114df1c291c22cac3b0c127a73e0af5c12ed7bbb6558d310429a0ae24023/coverage-7.10.7-py3-none-any.whl", hash = "sha256:f7941f6f2fe6dd6807a1208737b8a0cbcf1cc6d7b07d24998ad2d63590868260", size = 209952, upload-time = "2025-09-21T20:03:53.918Z" }, +] + [[package]] name = "deprecated" version = "1.2.18" @@ -602,6 +671,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/04/93/2fa34714b7a4ae72f2f8dad66ba17dd9a2c793220719e736dda28b7aec27/pytest_asyncio-1.2.0-py3-none-any.whl", hash = "sha256:8e17ae5e46d8e7efe51ab6494dd2010f4ca8dae51652aa3c8d55acf50bfb2e99", size = 15095, upload-time = "2025-09-12T07:33:52.639Z" }, ] +[[package]] +name = "pytest-cov" +version = "7.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "coverage" }, + { name = "pluggy" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5e/f7/c933acc76f5208b3b00089573cf6a2bc26dc80a8aece8f52bb7d6b1855ca/pytest_cov-7.0.0.tar.gz", hash = "sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1", size = 54328, upload-time = "2025-09-09T10:57:02.113Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861", size = 22424, upload-time = "2025-09-09T10:57:00.695Z" }, +] + [[package]] name = "python-dotenv" version = "1.1.1"