|
| 1 | +import importlib.util |
1 | 2 | import os |
2 | 3 | import sys |
3 | 4 | from pathlib import Path |
|
7 | 8 | os.environ.setdefault("ENCRYPTION_SECRET", "omi_ZwB2ZNqB2HHpMK6wStk7sTpavJiPTFg7gXUHnc4tFABPU6pZ2c2DKgehtfgi4RZv") |
8 | 9 |
|
9 | 10 | BACKEND_DIR = Path(__file__).resolve().parents[2] |
| 11 | +_BACKEND_DIR = str(BACKEND_DIR) |
10 | 12 |
|
11 | 13 |
|
12 | 14 | def _ensure_package(name, path): |
@@ -77,6 +79,87 @@ def _dependency(): |
77 | 79 | sys.modules.setdefault("firebase_admin", _mock_firebase) |
78 | 80 | sys.modules.setdefault("firebase_admin.auth", _mock_firebase.auth) |
79 | 81 |
|
| 82 | +if importlib.util.find_spec('python_multipart') is None and importlib.util.find_spec('multipart') is None: |
| 83 | + |
| 84 | + class _QuerystringParser: |
| 85 | + def __init__(self, callbacks): |
| 86 | + self._callbacks = callbacks |
| 87 | + self._buffer = bytearray() |
| 88 | + |
| 89 | + def write(self, data): |
| 90 | + self._buffer.extend(data) |
| 91 | + |
| 92 | + def finalize(self): |
| 93 | + for field in bytes(self._buffer).split(b'&'): |
| 94 | + if not field: |
| 95 | + continue |
| 96 | + name, _, value = field.partition(b'=') |
| 97 | + self._callbacks['on_field_start']() |
| 98 | + self._callbacks['on_field_name'](name, 0, len(name)) |
| 99 | + self._callbacks['on_field_data'](value, 0, len(value)) |
| 100 | + self._callbacks['on_field_end']() |
| 101 | + self._callbacks['on_end']() |
| 102 | + |
| 103 | + def _parse_options_header(value): |
| 104 | + if not value: |
| 105 | + return b'', {} |
| 106 | + if isinstance(value, str): |
| 107 | + value = value.encode('latin-1') |
| 108 | + content_type = value.split(b';', 1)[0].strip().lower() |
| 109 | + return content_type, {} |
| 110 | + |
| 111 | + _python_multipart = ModuleType('python_multipart') |
| 112 | + _python_multipart.QuerystringParser = _QuerystringParser |
| 113 | + _python_multipart_multipart = ModuleType('python_multipart.multipart') |
| 114 | + _python_multipart_multipart.parse_options_header = _parse_options_header |
| 115 | + sys.modules.setdefault('python_multipart', _python_multipart) |
| 116 | + sys.modules.setdefault('python_multipart.multipart', _python_multipart_multipart) |
| 117 | + |
| 118 | +_phone_calls_db = ModuleType('database.phone_calls') |
| 119 | +for _name in [ |
| 120 | + 'get_phone_number_by_number', |
| 121 | + 'set_pending_verification', |
| 122 | + 'get_pending_verification_uid', |
| 123 | + 'get_phone_numbers', |
| 124 | + 'upsert_phone_number', |
| 125 | + 'delete_pending_verification', |
| 126 | + 'get_phone_number', |
| 127 | + 'delete_phone_number', |
| 128 | + 'get_primary_phone_number', |
| 129 | +]: |
| 130 | + setattr(_phone_calls_db, _name, MagicMock()) |
| 131 | +sys.modules['database.phone_calls'] = _phone_calls_db |
| 132 | + |
| 133 | +_phone_call_usage_db = ModuleType('database.phone_call_usage') |
| 134 | +_phone_call_usage_db.get_current_month_count = MagicMock(return_value=(0, 0)) |
| 135 | +_phone_call_usage_db.increment_current_month = MagicMock() |
| 136 | +sys.modules['database.phone_call_usage'] = _phone_call_usage_db |
| 137 | +_database_pkg = sys.modules.setdefault('database', ModuleType('database')) |
| 138 | +_database_pkg.__path__ = [os.path.join(_BACKEND_DIR, 'database')] |
| 139 | +_database_pkg.phone_calls = _phone_calls_db |
| 140 | +_database_pkg.phone_call_usage = _phone_call_usage_db |
| 141 | + |
| 142 | +_phone_call_utils = ModuleType('utils.phone_calls') |
| 143 | +_phone_call_utils.check_call_access = MagicMock() |
| 144 | +_phone_call_utils.check_destination_allowed = MagicMock() |
| 145 | +_phone_call_utils.get_quota_snapshot = MagicMock( |
| 146 | + return_value=SimpleNamespace(has_access=True, is_paid=True, max_duration_seconds=None) |
| 147 | +) |
| 148 | +sys.modules['utils.phone_calls'] = _phone_call_utils |
| 149 | + |
| 150 | +_utils_other = ModuleType('utils.other') |
| 151 | +_utils_other.__path__ = [] |
| 152 | +_utils_other_endpoints = ModuleType('utils.other.endpoints') |
| 153 | +_utils_other_endpoints.get_current_user_uid = MagicMock() |
| 154 | +_utils_other_endpoints.rate_limit_dependency = lambda **_kwargs: (lambda: None) |
| 155 | +_utils_other.endpoints = _utils_other_endpoints |
| 156 | +sys.modules['utils.other'] = _utils_other |
| 157 | +sys.modules['utils.other.endpoints'] = _utils_other_endpoints |
| 158 | +_utils_pkg = sys.modules.setdefault('utils', ModuleType('utils')) |
| 159 | +_utils_pkg.__path__ = [os.path.join(_BACKEND_DIR, 'utils')] |
| 160 | +_utils_pkg.phone_calls = _phone_call_utils |
| 161 | +_utils_pkg.other = _utils_other |
| 162 | + |
80 | 163 |
|
81 | 164 | class _TwilioRestException(Exception): |
82 | 165 | def __init__(self, status=None, uri=None, msg='', code=None, method=None, details=None): |
|
0 commit comments