roksta 0.3.2__cp311-cp311-macosx_10_9_universal2.whl → 0.3.8__cp311-cp311-macosx_10_9_universal2.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- roksta/__init__.cpython-311-darwin.so +0 -0
- roksta/ai/__init__.cpython-311-darwin.so +0 -0
- roksta/ai/call_ai.cpython-311-darwin.so +0 -0
- roksta/ai/gemini.cpython-311-darwin.so +0 -0
- roksta/ai/generic.cpython-311-darwin.so +0 -0
- roksta/ai/llm.cpython-311-darwin.so +0 -0
- roksta/ai/openai.cpython-311-darwin.so +0 -0
- roksta/ai/tools/__init__.cpython-311-darwin.so +0 -0
- roksta/ai/tools/delete_file.cpython-311-darwin.so +0 -0
- roksta/ai/tools/edit_file.cpython-311-darwin.so +0 -0
- roksta/ai/tools/final_response.cpython-311-darwin.so +0 -0
- roksta/ai/tools/get_file_summaries.cpython-311-darwin.so +0 -0
- roksta/ai/tools/read_file.cpython-311-darwin.so +0 -0
- roksta/ai/tools/regex_replace.cpython-311-darwin.so +0 -0
- roksta/ai/tools/shell_any.cpython-311-darwin.so +0 -0
- roksta/ai/tools/shell_limited.cpython-311-darwin.so +0 -0
- roksta/ai/tools/tool_defs.cpython-311-darwin.so +0 -0
- roksta/ai/tools/tool_utils.cpython-311-darwin.so +0 -0
- roksta/ai/tools/web_fetch.cpython-311-darwin.so +0 -0
- roksta/ai/tools/write_file.cpython-311-darwin.so +0 -0
- roksta/analytics.cpython-311-darwin.so +0 -0
- roksta/balance.cpython-311-darwin.so +0 -0
- roksta/build_project.cpython-311-darwin.so +0 -0
- roksta/chat_workflow.cpython-311-darwin.so +0 -0
- roksta/check_for_updates.cpython-311-darwin.so +0 -0
- roksta/check_subtask_sequence.cpython-311-darwin.so +0 -0
- roksta/checkpoints.cpython-311-darwin.so +0 -0
- roksta/clarify_goal.cpython-311-darwin.so +0 -0
- roksta/codebase_listing.cpython-311-darwin.so +0 -0
- roksta/command_handlers/__init__.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_activate_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_add_funds_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_auto_charge_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_auto_commit_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_building_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_chat_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_dev_rate_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_feedback_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_goal_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_help_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_init_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_linting_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_login_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_logout_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_payment_details_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_quit_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_redeem_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_request_activation_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_testing_command.cpython-311-darwin.so +0 -0
- roksta/command_handlers/handle_usage_command.cpython-311-darwin.so +0 -0
- roksta/create_default_config.cpython-311-darwin.so +0 -0
- roksta/create_default_ignore_file.cpython-311-darwin.so +0 -0
- roksta/default_config.cpython-311-darwin.so +0 -0
- roksta/default_ignores.cpython-311-darwin.so +0 -0
- roksta/discover_test_command.cpython-311-darwin.so +0 -0
- roksta/enums.cpython-311-darwin.so +0 -0
- roksta/env.cpython-311-darwin.so +0 -0
- roksta/extended_text_area.cpython-311-darwin.so +0 -0
- roksta/firebase.cpython-311-darwin.so +0 -0
- roksta/firebase_auth_web.cpython-311-darwin.so +0 -0
- roksta/firebase_config.cpython-311-darwin.so +0 -0
- roksta/fix_tests.cpython-311-darwin.so +0 -0
- roksta/gen_codebase_summaries.cpython-311-darwin.so +0 -0
- roksta/gen_one_line_goal.cpython-311-darwin.so +0 -0
- roksta/gen_subtasks.cpython-311-darwin.so +0 -0
- roksta/get_codebase_structure.cpython-311-darwin.so +0 -0
- roksta/get_failing_tests.cpython-311-darwin.so +0 -0
- roksta/goal_workflow.cpython-311-darwin.so +0 -0
- roksta/init_codebase.cpython-311-darwin.so +0 -0
- roksta/lint_code.cpython-311-darwin.so +0 -0
- roksta/logger.cpython-311-darwin.so +0 -0
- roksta/main.cpython-311-darwin.so +0 -0
- roksta/make_issue.cpython-311-darwin.so +0 -0
- roksta/new_features.cpython-311-darwin.so +0 -0
- roksta/parse_directive_cli_tokens.cpython-311-darwin.so +0 -0
- roksta/parse_readme.cpython-311-darwin.so +0 -0
- roksta/propose_solution.cpython-311-darwin.so +0 -0
- roksta/response_formats.cpython-311-darwin.so +0 -0
- roksta/rewrite_goal.cpython-311-darwin.so +0 -0
- roksta/roksta.cpython-311-darwin.so +0 -0
- roksta/run_cli_goal.cpython-311-darwin.so +0 -0
- roksta/save_chat_transcript.cpython-311-darwin.so +0 -0
- roksta/select_files.cpython-311-darwin.so +0 -0
- roksta/tips.cpython-311-darwin.so +0 -0
- roksta/utils.cpython-311-darwin.so +0 -0
- roksta/write_code.cpython-311-darwin.so +0 -0
- roksta-0.3.8.dist-info/METADATA +471 -0
- roksta-0.3.8.dist-info/RECORD +91 -0
- {roksta-0.3.2.dist-info → roksta-0.3.8.dist-info}/top_level.txt +0 -1
- roksta-0.3.2.dist-info/METADATA +0 -40
- roksta-0.3.2.dist-info/RECORD +0 -121
- tests/__init__.py +0 -2
- tests/conftest.py +0 -211
- tests/functions/__init__.py +0 -2
- tests/functions/api_v1_00/__init__.py +0 -2
- tests/functions/api_v1_00/test__analytics.py +0 -416
- tests/functions/api_v1_00/test__gemini_proxy.py +0 -352
- tests/functions/api_v1_00/test__generic_proxy.py +0 -428
- tests/functions/api_v1_00/test__get_payment_details.py +0 -356
- tests/functions/api_v1_00/test__openai_proxy.py +0 -449
- tests/functions/api_v1_00/test__redeem_credit_code.py +0 -167
- tests/functions/api_v1_00/test__sync_emails.py +0 -325
- tests/functions/api_v1_00/test__take_payment.py +0 -491
- tests/functions/api_v1_00/test__use_activation_code.py +0 -438
- tests/functions/api_v1_01/__init__.py +0 -2
- tests/functions/api_v1_01/test__analytics.py +0 -416
- tests/functions/api_v1_01/test__gemini_proxy.py +0 -352
- tests/functions/api_v1_01/test__generic_proxy.py +0 -428
- tests/functions/api_v1_01/test__get_payment_details.py +0 -356
- tests/functions/api_v1_01/test__openai_proxy.py +0 -449
- tests/functions/api_v1_01/test__redeem_credit_code.py +0 -167
- tests/functions/api_v1_01/test__sync_emails.py +0 -325
- tests/functions/api_v1_01/test__take_payment.py +0 -491
- tests/functions/api_v1_01/test__use_activation_code.py +0 -438
- tests/functions/api_v1_02/__init__.py +0 -2
- tests/functions/api_v1_02/test__analytics.py +0 -416
- tests/functions/api_v1_02/test__gemini_proxy.py +0 -352
- tests/functions/api_v1_02/test__generic_proxy.py +0 -428
- tests/functions/api_v1_02/test__get_payment_details.py +0 -356
- tests/functions/api_v1_02/test__openai_proxy.py +0 -449
- tests/functions/api_v1_02/test__redeem_credit_code.py +0 -167
- tests/functions/api_v1_02/test__sync_emails.py +0 -325
- tests/functions/api_v1_02/test__take_payment.py +0 -491
- tests/functions/api_v1_02/test__use_activation_code.py +0 -438
- tests/functions/api_v1_02/test_proxy_keyword_replacement.py +0 -557
- tests/functions/api_v1_02/test_replace_keywords.py +0 -74
- tests/functions/test_auth.py +0 -24
- tests/functions/test_main.py +0 -73
- tests/functions/test_utils.py +0 -484
- {roksta-0.3.2.dist-info → roksta-0.3.8.dist-info}/WHEEL +0 -0
- {roksta-0.3.2.dist-info → roksta-0.3.8.dist-info}/entry_points.txt +0 -0
|
@@ -1,557 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import sys
|
|
3
|
-
import json
|
|
4
|
-
import types
|
|
5
|
-
import importlib
|
|
6
|
-
import importlib.util
|
|
7
|
-
from unittest.mock import patch
|
|
8
|
-
|
|
9
|
-
# Ensure the functions/ directory is importable as a top-level module location
|
|
10
|
-
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
|
|
11
|
-
FUNCTIONS_DIR = os.path.join(PROJECT_ROOT, 'functions')
|
|
12
|
-
if FUNCTIONS_DIR not in sys.path:
|
|
13
|
-
sys.path.insert(0, FUNCTIONS_DIR)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
# Helper: Fake firebase_functions.Response used to capture returned data
|
|
17
|
-
class FakeResponse:
|
|
18
|
-
def __init__(self, response=None, mimetype=None, status=200, **kwargs):
|
|
19
|
-
self.status_code = status
|
|
20
|
-
if isinstance(response, (dict, list)):
|
|
21
|
-
self._body_text = json.dumps(response)
|
|
22
|
-
else:
|
|
23
|
-
self._body_text = '' if response is None else response
|
|
24
|
-
self.headers = kwargs.get('headers', {})
|
|
25
|
-
|
|
26
|
-
def get_data(self, as_text=False):
|
|
27
|
-
if as_text:
|
|
28
|
-
return self._body_text
|
|
29
|
-
return self._body_text.encode('utf-8')
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class DummyRequest:
|
|
33
|
-
def __init__(self, headers=None, method='POST', json_data=None, raise_on_get_json=False):
|
|
34
|
-
self.headers = headers or {}
|
|
35
|
-
self.method = method
|
|
36
|
-
self._json_data = json_data
|
|
37
|
-
self._raise = raise_on_get_json
|
|
38
|
-
|
|
39
|
-
def get_json(self, silent=False):
|
|
40
|
-
if self._raise:
|
|
41
|
-
raise Exception('Malformed JSON')
|
|
42
|
-
return self._json_data
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def _parse_response(resp):
|
|
46
|
-
data = resp.get_data(as_text=True)
|
|
47
|
-
return json.loads(data)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
# -----------------------------
|
|
51
|
-
# Tests for OpenAI proxy (v1_02)
|
|
52
|
-
# -----------------------------
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def test_openai_create_replacement_applied_to_input():
|
|
56
|
-
# Prepare fake modules to satisfy imports inside _openai_proxy
|
|
57
|
-
_orig_sys_modules = {}
|
|
58
|
-
names_to_fake = ['firebase_functions', 'utils', 'auth', 'openai', 'firebase_admin', 'billing']
|
|
59
|
-
for name in names_to_fake:
|
|
60
|
-
_orig_sys_modules[name] = sys.modules.get(name)
|
|
61
|
-
|
|
62
|
-
# Fake firebase_functions
|
|
63
|
-
firebase_functions = types.ModuleType('firebase_functions')
|
|
64
|
-
firebase_functions.https_fn = types.SimpleNamespace(Request=object, Response=FakeResponse)
|
|
65
|
-
sys.modules['firebase_functions'] = firebase_functions
|
|
66
|
-
|
|
67
|
-
# Fake utils (create_json_response etc.)
|
|
68
|
-
utils_mod = types.ModuleType('utils')
|
|
69
|
-
|
|
70
|
-
def _fake_create_json_response(success: bool, payload: any, status_code: int):
|
|
71
|
-
response_body = {"success": success, "payload": payload}
|
|
72
|
-
return FakeResponse(response=json.dumps(response_body), status=status_code, headers={'Content-Type': 'application/json'})
|
|
73
|
-
|
|
74
|
-
def _fake_get_api_key(llm_family=None):
|
|
75
|
-
return 'DUMMY_KEY'
|
|
76
|
-
|
|
77
|
-
def _fake_verify_firebase_token(req):
|
|
78
|
-
return {}
|
|
79
|
-
|
|
80
|
-
def _fake_get_request_json(req, strict=False):
|
|
81
|
-
return req.get_json(silent=not strict)
|
|
82
|
-
|
|
83
|
-
utils_mod.create_json_response = _fake_create_json_response
|
|
84
|
-
utils_mod.get_api_key = _fake_get_api_key
|
|
85
|
-
utils_mod.verify_firebase_token = _fake_verify_firebase_token
|
|
86
|
-
utils_mod.get_request_json = _fake_get_request_json
|
|
87
|
-
sys.modules['utils'] = utils_mod
|
|
88
|
-
|
|
89
|
-
# Fake auth
|
|
90
|
-
auth_mod = types.ModuleType('auth')
|
|
91
|
-
auth_mod.validate_auth_key = lambda v: True
|
|
92
|
-
sys.modules['auth'] = auth_mod
|
|
93
|
-
|
|
94
|
-
# Fake openai module - will be patched into module under test
|
|
95
|
-
openai_mod = types.ModuleType('openai')
|
|
96
|
-
class DummyOpenAI:
|
|
97
|
-
def __init__(self, api_key=None, timeout=None):
|
|
98
|
-
self.api_key = api_key
|
|
99
|
-
self.timeout = timeout
|
|
100
|
-
self.responses = self
|
|
101
|
-
def create(self, **params):
|
|
102
|
-
raise NotImplementedError()
|
|
103
|
-
def parse(self, **params):
|
|
104
|
-
raise NotImplementedError()
|
|
105
|
-
openai_mod.OpenAI = DummyOpenAI
|
|
106
|
-
openai_mod.APIError = Exception
|
|
107
|
-
sys.modules['openai'] = openai_mod
|
|
108
|
-
|
|
109
|
-
# Fake billing
|
|
110
|
-
billing_mod = types.ModuleType('billing')
|
|
111
|
-
billing_mod.ensure_balance_positive = lambda db, user_id: (True, 100.0)
|
|
112
|
-
billing_mod.calculate_cost = lambda model_id, in_t, out_t: 0.0
|
|
113
|
-
billing_mod.bill_with_retry = lambda db, user_id, model_id, usage, cost, reason='usage': ("ok", 100.0)
|
|
114
|
-
sys.modules['billing'] = billing_mod
|
|
115
|
-
|
|
116
|
-
# Fake firebase_admin
|
|
117
|
-
firebase_admin_mod = types.ModuleType('firebase_admin')
|
|
118
|
-
firebase_admin_mod.firestore = types.SimpleNamespace(client=lambda: types.SimpleNamespace(), Client=type('Client', (), {}))
|
|
119
|
-
sys.modules['firebase_admin'] = firebase_admin_mod
|
|
120
|
-
|
|
121
|
-
# Import the package and module under test
|
|
122
|
-
repo_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
|
|
123
|
-
functions_root = os.path.join(repo_root, 'functions')
|
|
124
|
-
pkg_init = os.path.join(functions_root, 'api_v1_02', '__init__.py')
|
|
125
|
-
spec_pkg = importlib.util.spec_from_file_location('api_v1_02', pkg_init)
|
|
126
|
-
pkg = importlib.util.module_from_spec(spec_pkg)
|
|
127
|
-
spec_pkg.loader.exec_module(pkg)
|
|
128
|
-
sys.modules['api_v1_02'] = pkg
|
|
129
|
-
|
|
130
|
-
module_path = os.path.join(functions_root, 'api_v1_02', '_openai_proxy.py')
|
|
131
|
-
spec = importlib.util.spec_from_file_location('api_v1_02._openai_proxy', module_path)
|
|
132
|
-
_openai = importlib.util.module_from_spec(spec)
|
|
133
|
-
spec.loader.exec_module(_openai)
|
|
134
|
-
|
|
135
|
-
# Cleanup sys.modules fakes after import
|
|
136
|
-
for name, orig in _orig_sys_modules.items():
|
|
137
|
-
if orig is None:
|
|
138
|
-
try:
|
|
139
|
-
del sys.modules[name]
|
|
140
|
-
except KeyError:
|
|
141
|
-
pass
|
|
142
|
-
else:
|
|
143
|
-
sys.modules[name] = orig
|
|
144
|
-
|
|
145
|
-
# Prepare request with keyword in input
|
|
146
|
-
headers = {_openai.AUTH_HEADER_NAME: 'ok'}
|
|
147
|
-
req_payload = {'call_type': 'create', 'call_params': {'model': 'gem-model', 'input': 'Hello ==SELECT_FILE_INSTRUCTIONS== world'}}
|
|
148
|
-
req = DummyRequest(headers=headers, method='POST', json_data=req_payload)
|
|
149
|
-
|
|
150
|
-
# Fake client to capture params passed to create
|
|
151
|
-
class FakeClient:
|
|
152
|
-
last_create_params = None
|
|
153
|
-
def __init__(self, api_key, timeout=None):
|
|
154
|
-
self.api_key = api_key
|
|
155
|
-
self.timeout = timeout
|
|
156
|
-
self.responses = self
|
|
157
|
-
def create(self, **params):
|
|
158
|
-
FakeClient.last_create_params = params
|
|
159
|
-
class FakeResp:
|
|
160
|
-
def model_dump(self_inner, mode='json'):
|
|
161
|
-
return {'result': 'ok', 'received_model': params.get('model'), 'usage': {'input_tokens': 1, 'output_tokens': 2}}
|
|
162
|
-
return FakeResp()
|
|
163
|
-
|
|
164
|
-
with patch.object(_openai, 'validate_auth_key', return_value=True), \
|
|
165
|
-
patch.object(_openai, 'verify_firebase_token', return_value={}), \
|
|
166
|
-
patch.object(_openai, 'get_api_key', return_value='OPENAI-KEY'), \
|
|
167
|
-
patch.object(_openai.openai, 'OpenAI', FakeClient):
|
|
168
|
-
resp = _openai._openai_proxy(req)
|
|
169
|
-
|
|
170
|
-
payload = _parse_response(resp)
|
|
171
|
-
assert resp.status_code == 200
|
|
172
|
-
assert payload['success'] is True
|
|
173
|
-
assert FakeClient.last_create_params is not None
|
|
174
|
-
inp = str(FakeClient.last_create_params.get('input', ''))
|
|
175
|
-
assert ('Some instructions for selecting files' in inp) or ('files in my codebase' in inp)
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
def test_openai_parse_replacement_applied_to_input():
|
|
179
|
-
# Similar setup as create test
|
|
180
|
-
_orig_sys_modules = {}
|
|
181
|
-
names_to_fake = ['firebase_functions', 'utils', 'auth', 'openai', 'firebase_admin', 'billing']
|
|
182
|
-
for name in names_to_fake:
|
|
183
|
-
_orig_sys_modules[name] = sys.modules.get(name)
|
|
184
|
-
|
|
185
|
-
firebase_functions = types.ModuleType('firebase_functions')
|
|
186
|
-
firebase_functions.https_fn = types.SimpleNamespace(Request=object, Response=FakeResponse)
|
|
187
|
-
sys.modules['firebase_functions'] = firebase_functions
|
|
188
|
-
|
|
189
|
-
utils_mod = types.ModuleType('utils')
|
|
190
|
-
def _fake_create_json_response(success: bool, payload: any, status_code: int):
|
|
191
|
-
response_body = {"success": success, "payload": payload}
|
|
192
|
-
return FakeResponse(response=json.dumps(response_body), status=status_code, headers={'Content-Type': 'application/json'})
|
|
193
|
-
def _fake_get_api_key(llm_family=None):
|
|
194
|
-
return 'DUMMY_KEY'
|
|
195
|
-
def _fake_verify_firebase_token(req):
|
|
196
|
-
return {}
|
|
197
|
-
def _fake_get_request_json(req, strict=False):
|
|
198
|
-
return req.get_json(silent=not strict)
|
|
199
|
-
utils_mod.create_json_response = _fake_create_json_response
|
|
200
|
-
utils_mod.get_api_key = _fake_get_api_key
|
|
201
|
-
utils_mod.verify_firebase_token = _fake_verify_firebase_token
|
|
202
|
-
utils_mod.get_request_json = _fake_get_request_json
|
|
203
|
-
sys.modules['utils'] = utils_mod
|
|
204
|
-
|
|
205
|
-
auth_mod = types.ModuleType('auth')
|
|
206
|
-
auth_mod.validate_auth_key = lambda v: True
|
|
207
|
-
sys.modules['auth'] = auth_mod
|
|
208
|
-
|
|
209
|
-
openai_mod = types.ModuleType('openai')
|
|
210
|
-
class DummyOpenAI:
|
|
211
|
-
def __init__(self, api_key=None, timeout=None):
|
|
212
|
-
self.api_key = api_key
|
|
213
|
-
self.timeout = timeout
|
|
214
|
-
self.responses = self
|
|
215
|
-
def create(self, **params):
|
|
216
|
-
raise NotImplementedError()
|
|
217
|
-
def parse(self, **params):
|
|
218
|
-
raise NotImplementedError()
|
|
219
|
-
openai_mod.OpenAI = DummyOpenAI
|
|
220
|
-
openai_mod.APIError = Exception
|
|
221
|
-
sys.modules['openai'] = openai_mod
|
|
222
|
-
|
|
223
|
-
billing_mod = types.ModuleType('billing')
|
|
224
|
-
billing_mod.ensure_balance_positive = lambda db, user_id: (True, 100.0)
|
|
225
|
-
billing_mod.calculate_cost = lambda model_id, in_t, out_t: 0.0
|
|
226
|
-
billing_mod.bill_with_retry = lambda db, user_id, model_id, usage, cost, reason='usage': ("ok", 100.0)
|
|
227
|
-
sys.modules['billing'] = billing_mod
|
|
228
|
-
|
|
229
|
-
firebase_admin_mod = types.ModuleType('firebase_admin')
|
|
230
|
-
firebase_admin_mod.firestore = types.SimpleNamespace(client=lambda: types.SimpleNamespace(), Client=type('Client', (), {}))
|
|
231
|
-
sys.modules['firebase_admin'] = firebase_admin_mod
|
|
232
|
-
|
|
233
|
-
# Import package and module
|
|
234
|
-
repo_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
|
|
235
|
-
functions_root = os.path.join(repo_root, 'functions')
|
|
236
|
-
pkg_init = os.path.join(functions_root, 'api_v1_02', '__init__.py')
|
|
237
|
-
spec_pkg = importlib.util.spec_from_file_location('api_v1_02', pkg_init)
|
|
238
|
-
pkg = importlib.util.module_from_spec(spec_pkg)
|
|
239
|
-
spec_pkg.loader.exec_module(pkg)
|
|
240
|
-
sys.modules['api_v1_02'] = pkg
|
|
241
|
-
|
|
242
|
-
module_path = os.path.join(functions_root, 'api_v1_02', '_openai_proxy.py')
|
|
243
|
-
spec = importlib.util.spec_from_file_location('api_v1_02._openai_proxy', module_path)
|
|
244
|
-
_openai = importlib.util.module_from_spec(spec)
|
|
245
|
-
spec.loader.exec_module(_openai)
|
|
246
|
-
|
|
247
|
-
for name, orig in _orig_sys_modules.items():
|
|
248
|
-
if orig is None:
|
|
249
|
-
try:
|
|
250
|
-
del sys.modules[name]
|
|
251
|
-
except KeyError:
|
|
252
|
-
pass
|
|
253
|
-
else:
|
|
254
|
-
sys.modules[name] = orig
|
|
255
|
-
|
|
256
|
-
headers = {_openai.AUTH_HEADER_NAME: 'ok'}
|
|
257
|
-
req_payload = {'call_type': 'parse', 'call_params': {'model': 'gem-model', 'input': 'Hello ==SELECT_FILE_INSTRUCTIONS==', 'text_format': 'FileSummaryModel'}}
|
|
258
|
-
req = DummyRequest(headers=headers, method='POST', json_data=req_payload)
|
|
259
|
-
|
|
260
|
-
class FakeClient2:
|
|
261
|
-
last_parse_params = None
|
|
262
|
-
def __init__(self, api_key, timeout=None):
|
|
263
|
-
self.api_key = api_key
|
|
264
|
-
self.timeout = timeout
|
|
265
|
-
self.responses = self
|
|
266
|
-
def parse(self, **params):
|
|
267
|
-
FakeClient2.last_parse_params = params
|
|
268
|
-
class FakeOutputParsed:
|
|
269
|
-
def __init__(self, data):
|
|
270
|
-
self._data = data
|
|
271
|
-
def dict(self):
|
|
272
|
-
return self._data
|
|
273
|
-
class FakeResp:
|
|
274
|
-
def __init__(self, data):
|
|
275
|
-
self.output_parsed = FakeOutputParsed(data)
|
|
276
|
-
def model_dump(self_inner, mode='json'):
|
|
277
|
-
return {'usage': {'input_tokens': 1, 'output_tokens': 2}}
|
|
278
|
-
parsed = {'result': 'ok', 'received_model': params.get('model')}
|
|
279
|
-
return FakeResp(parsed)
|
|
280
|
-
|
|
281
|
-
with patch.object(_openai, 'validate_auth_key', return_value=True), \
|
|
282
|
-
patch.object(_openai, 'verify_firebase_token', return_value={}), \
|
|
283
|
-
patch.object(_openai, 'get_api_key', return_value='OPENAI-KEY'), \
|
|
284
|
-
patch.object(_openai.openai, 'OpenAI', FakeClient2):
|
|
285
|
-
resp = _openai._openai_proxy(req)
|
|
286
|
-
|
|
287
|
-
payload = _parse_response(resp)
|
|
288
|
-
assert resp.status_code == 200
|
|
289
|
-
assert payload['success'] is True
|
|
290
|
-
assert FakeClient2.last_parse_params is not None
|
|
291
|
-
inp = str(FakeClient2.last_parse_params.get('input', ''))
|
|
292
|
-
assert ('Some instructions for selecting files' in inp) or ('files in my codebase' in inp)
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
# -----------------------------
|
|
296
|
-
# Tests for Generic proxy (v1_02)
|
|
297
|
-
# -----------------------------
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
def test_generic_create_replacement_applied_to_input():
|
|
301
|
-
_orig_sys_modules = {}
|
|
302
|
-
names_to_fake = ['firebase_functions', 'utils', 'auth', 'openai', 'firebase_admin', 'billing']
|
|
303
|
-
for name in names_to_fake:
|
|
304
|
-
_orig_sys_modules[name] = sys.modules.get(name)
|
|
305
|
-
|
|
306
|
-
firebase_functions = types.ModuleType('firebase_functions')
|
|
307
|
-
firebase_functions.https_fn = types.SimpleNamespace(Request=object, Response=FakeResponse)
|
|
308
|
-
sys.modules['firebase_functions'] = firebase_functions
|
|
309
|
-
|
|
310
|
-
utils_mod = types.ModuleType('utils')
|
|
311
|
-
def _fake_create_json_response(success: bool, payload: any, status_code: int):
|
|
312
|
-
response_body = {"success": success, "payload": payload}
|
|
313
|
-
return FakeResponse(response=json.dumps(response_body), status=status_code, headers={'Content-Type': 'application/json'})
|
|
314
|
-
def _fake_get_api_key(llm_family=None):
|
|
315
|
-
return 'DUMMY_KEY'
|
|
316
|
-
def _fake_verify_firebase_token(req):
|
|
317
|
-
return {}
|
|
318
|
-
def _fake_get_request_json(req, strict=False):
|
|
319
|
-
return req.get_json(silent=not strict)
|
|
320
|
-
utils_mod.create_json_response = _fake_create_json_response
|
|
321
|
-
utils_mod.get_api_key = _fake_get_api_key
|
|
322
|
-
utils_mod.verify_firebase_token = _fake_verify_firebase_token
|
|
323
|
-
utils_mod.get_request_json = _fake_get_request_json
|
|
324
|
-
sys.modules['utils'] = utils_mod
|
|
325
|
-
|
|
326
|
-
auth_mod = types.ModuleType('auth')
|
|
327
|
-
auth_mod.validate_auth_key = lambda v: True
|
|
328
|
-
sys.modules['auth'] = auth_mod
|
|
329
|
-
|
|
330
|
-
# Fake openai client
|
|
331
|
-
openai_mod = types.ModuleType('openai')
|
|
332
|
-
class DummyOpenAI:
|
|
333
|
-
def __init__(self, base_url=None, api_key=None, timeout=None):
|
|
334
|
-
self.base_url = base_url
|
|
335
|
-
self.api_key = api_key
|
|
336
|
-
self.timeout = timeout
|
|
337
|
-
class Completions:
|
|
338
|
-
def create(self, **params):
|
|
339
|
-
raise NotImplementedError()
|
|
340
|
-
def parse(self, **params):
|
|
341
|
-
raise NotImplementedError()
|
|
342
|
-
class Chat:
|
|
343
|
-
def __init__(self):
|
|
344
|
-
self.completions = Completions()
|
|
345
|
-
self.chat = Chat()
|
|
346
|
-
openai_mod.OpenAI = DummyOpenAI
|
|
347
|
-
openai_mod.APIError = Exception
|
|
348
|
-
sys.modules['openai'] = openai_mod
|
|
349
|
-
|
|
350
|
-
# Fake billing
|
|
351
|
-
billing_mod = types.ModuleType('billing')
|
|
352
|
-
billing_mod.ensure_balance_positive = lambda db, user_id: (True, 100.0)
|
|
353
|
-
billing_mod.calculate_cost = lambda model_id, in_t, out_t: 0.0
|
|
354
|
-
billing_mod.bill_with_retry = lambda db, user_id, model_id, usage, cost, reason='usage': ("ok", 100.0)
|
|
355
|
-
sys.modules['billing'] = billing_mod
|
|
356
|
-
|
|
357
|
-
# Fake firebase_admin
|
|
358
|
-
firebase_admin_mod = types.ModuleType('firebase_admin')
|
|
359
|
-
firebase_admin_mod.firestore = types.SimpleNamespace(client=lambda: types.SimpleNamespace(), Client=type('Client', (), {}))
|
|
360
|
-
sys.modules['firebase_admin'] = firebase_admin_mod
|
|
361
|
-
|
|
362
|
-
# Import package and module
|
|
363
|
-
repo_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
|
|
364
|
-
functions_root = os.path.join(repo_root, 'functions')
|
|
365
|
-
pkg_init = os.path.join(functions_root, 'api_v1_02', '__init__.py')
|
|
366
|
-
spec_pkg = importlib.util.spec_from_file_location('api_v1_02', pkg_init)
|
|
367
|
-
pkg = importlib.util.module_from_spec(spec_pkg)
|
|
368
|
-
spec_pkg.loader.exec_module(pkg)
|
|
369
|
-
sys.modules['api_v1_02'] = pkg
|
|
370
|
-
|
|
371
|
-
module_path = os.path.join(functions_root, 'api_v1_02', '_generic_proxy.py')
|
|
372
|
-
spec = importlib.util.spec_from_file_location('api_v1_02._generic_proxy', module_path)
|
|
373
|
-
_generic = importlib.util.module_from_spec(spec)
|
|
374
|
-
spec.loader.exec_module(_generic)
|
|
375
|
-
|
|
376
|
-
for name, orig in _orig_sys_modules.items():
|
|
377
|
-
if orig is None:
|
|
378
|
-
try:
|
|
379
|
-
del sys.modules[name]
|
|
380
|
-
except KeyError:
|
|
381
|
-
pass
|
|
382
|
-
else:
|
|
383
|
-
sys.modules[name] = orig
|
|
384
|
-
|
|
385
|
-
headers = {_generic.AUTH_HEADER_NAME: 'ok'}
|
|
386
|
-
req_payload = {'llm_family': 'openai', 'call_type': 'create', 'call_params': {'model': 'gem-model', 'input': 'Hello ==SELECT_FILE_INSTRUCTIONS=='}}
|
|
387
|
-
req = DummyRequest(headers=headers, method='POST', json_data=req_payload)
|
|
388
|
-
|
|
389
|
-
class FakeClient:
|
|
390
|
-
last_create_params = None
|
|
391
|
-
def __init__(self, base_url=None, api_key=None, timeout=None):
|
|
392
|
-
self.base_url = base_url
|
|
393
|
-
self.api_key = api_key
|
|
394
|
-
class Completions:
|
|
395
|
-
def create(self_inner, **params):
|
|
396
|
-
FakeClient.last_create_params = params
|
|
397
|
-
class FakeResp:
|
|
398
|
-
def model_dump(self_inner2, mode='json'):
|
|
399
|
-
return {'result': 'ok', 'received_model': params.get('model'), 'usage': {'prompt_tokens': 1, 'completion_tokens': 2}}
|
|
400
|
-
return FakeResp()
|
|
401
|
-
def parse(self_inner, **params):
|
|
402
|
-
raise NotImplementedError()
|
|
403
|
-
class Chat:
|
|
404
|
-
def __init__(self):
|
|
405
|
-
self.completions = Completions()
|
|
406
|
-
self.chat = Chat()
|
|
407
|
-
|
|
408
|
-
with patch.object(_generic, 'validate_auth_key', return_value=True), \
|
|
409
|
-
patch.object(_generic, 'verify_firebase_token', return_value={}), \
|
|
410
|
-
patch.object(_generic, 'get_api_key', return_value='GENERIC-KEY'), \
|
|
411
|
-
patch.object(_generic.openai, 'OpenAI', FakeClient):
|
|
412
|
-
resp = _generic._generic_proxy(req)
|
|
413
|
-
|
|
414
|
-
payload = _parse_response(resp)
|
|
415
|
-
assert resp.status_code == 200
|
|
416
|
-
assert payload['success'] is True
|
|
417
|
-
assert FakeClient.last_create_params is not None
|
|
418
|
-
inp = str(FakeClient.last_create_params.get('input', ''))
|
|
419
|
-
assert ('Some instructions for selecting files' in inp) or ('files in my codebase' in inp)
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
# -----------------------------
|
|
423
|
-
# Tests for Gemini proxy (v1_02)
|
|
424
|
-
# -----------------------------
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
def test_gemini_generate_content_replacement_applied_to_contents():
|
|
428
|
-
_orig_sys_modules = {}
|
|
429
|
-
names_to_fake = ['firebase_functions', 'utils', 'auth', 'google', 'google.genai', 'google.genai.types', 'firebase_admin', 'billing']
|
|
430
|
-
for name in names_to_fake:
|
|
431
|
-
_orig_sys_modules[name] = sys.modules.get(name)
|
|
432
|
-
|
|
433
|
-
firebase_functions = types.ModuleType('firebase_functions')
|
|
434
|
-
firebase_functions.https_fn = types.SimpleNamespace(Request=object, Response=FakeResponse)
|
|
435
|
-
sys.modules['firebase_functions'] = firebase_functions
|
|
436
|
-
|
|
437
|
-
# Fake utils
|
|
438
|
-
utils_mod = types.ModuleType('utils')
|
|
439
|
-
def _fake_create_json_response(success: bool, payload: any, status_code: int):
|
|
440
|
-
response_body = {"success": success, "payload": payload}
|
|
441
|
-
return FakeResponse(response=json.dumps(response_body), status=status_code, headers={'Content-Type': 'application/json'})
|
|
442
|
-
def _fake_get_api_key(llm_family=None):
|
|
443
|
-
return 'DUMMY_KEY'
|
|
444
|
-
def _fake_verify_firebase_token(req):
|
|
445
|
-
return {}
|
|
446
|
-
def _fake_get_request_json(req, strict=False):
|
|
447
|
-
return req.get_json(silent=not strict)
|
|
448
|
-
utils_mod.create_json_response = _fake_create_json_response
|
|
449
|
-
utils_mod.get_api_key = _fake_get_api_key
|
|
450
|
-
utils_mod.verify_firebase_token = _fake_verify_firebase_token
|
|
451
|
-
utils_mod.get_request_json = _fake_get_request_json
|
|
452
|
-
sys.modules['utils'] = utils_mod
|
|
453
|
-
|
|
454
|
-
auth_mod = types.ModuleType('auth')
|
|
455
|
-
auth_mod.validate_auth_key = lambda v: True
|
|
456
|
-
sys.modules['auth'] = auth_mod
|
|
457
|
-
|
|
458
|
-
# Fake google.genai types
|
|
459
|
-
google_mod = types.ModuleType('google')
|
|
460
|
-
genai_mod = types.ModuleType('google.genai')
|
|
461
|
-
types_mod = types.ModuleType('google.genai.types')
|
|
462
|
-
|
|
463
|
-
class DummyGenerateContentConfig:
|
|
464
|
-
def __init__(self, **kwargs):
|
|
465
|
-
self.kwargs = kwargs
|
|
466
|
-
|
|
467
|
-
class DummyContent:
|
|
468
|
-
def __init__(self, **kwargs):
|
|
469
|
-
self.kwargs = kwargs
|
|
470
|
-
|
|
471
|
-
types_mod.GenerateContentConfig = DummyGenerateContentConfig
|
|
472
|
-
types_mod.Content = DummyContent
|
|
473
|
-
|
|
474
|
-
class DummyClient:
|
|
475
|
-
def __init__(self, api_key):
|
|
476
|
-
self.api_key = api_key
|
|
477
|
-
class Models:
|
|
478
|
-
def generate_content(self_inner, **params):
|
|
479
|
-
raise NotImplementedError()
|
|
480
|
-
self.models = Models()
|
|
481
|
-
|
|
482
|
-
genai_mod.Client = DummyClient
|
|
483
|
-
genai_mod.types = types_mod
|
|
484
|
-
google_mod.genai = genai_mod
|
|
485
|
-
|
|
486
|
-
sys.modules['google'] = google_mod
|
|
487
|
-
sys.modules['google.genai'] = genai_mod
|
|
488
|
-
sys.modules['google.genai.types'] = types_mod
|
|
489
|
-
|
|
490
|
-
billing_mod = types.ModuleType('billing')
|
|
491
|
-
billing_mod.ensure_balance_positive = lambda db, user_id: (True, 100.0)
|
|
492
|
-
billing_mod.calculate_cost = lambda model_id, in_t, out_t: 0.0
|
|
493
|
-
billing_mod.bill_with_retry = lambda db, user_id, model_id, usage, cost, reason='usage': ("ok", 100.0)
|
|
494
|
-
sys.modules['billing'] = billing_mod
|
|
495
|
-
|
|
496
|
-
firebase_admin_mod = types.ModuleType('firebase_admin')
|
|
497
|
-
firebase_admin_mod.firestore = types.SimpleNamespace(client=lambda: types.SimpleNamespace(), Client=type('Client', (), {}))
|
|
498
|
-
sys.modules['firebase_admin'] = firebase_admin_mod
|
|
499
|
-
|
|
500
|
-
# Import package and module
|
|
501
|
-
repo_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
|
|
502
|
-
functions_root = os.path.join(repo_root, 'functions')
|
|
503
|
-
pkg_init = os.path.join(functions_root, 'api_v1_02', '__init__.py')
|
|
504
|
-
spec_pkg = importlib.util.spec_from_file_location('api_v1_02', pkg_init)
|
|
505
|
-
pkg = importlib.util.module_from_spec(spec_pkg)
|
|
506
|
-
spec_pkg.loader.exec_module(pkg)
|
|
507
|
-
sys.modules['api_v1_02'] = pkg
|
|
508
|
-
|
|
509
|
-
module_path = os.path.join(functions_root, 'api_v1_02', '_gemini_proxy.py')
|
|
510
|
-
spec = importlib.util.spec_from_file_location('api_v1_02._gemini_proxy', module_path)
|
|
511
|
-
_gemini = importlib.util.module_from_spec(spec)
|
|
512
|
-
spec.loader.exec_module(_gemini)
|
|
513
|
-
|
|
514
|
-
# Restore sys.modules
|
|
515
|
-
for name, orig in _orig_sys_modules.items():
|
|
516
|
-
if orig is None:
|
|
517
|
-
try:
|
|
518
|
-
del sys.modules[name]
|
|
519
|
-
except KeyError:
|
|
520
|
-
pass
|
|
521
|
-
else:
|
|
522
|
-
sys.modules[name] = orig
|
|
523
|
-
|
|
524
|
-
headers = {_gemini.AUTH_HEADER_NAME: 'ok'}
|
|
525
|
-
json_params = {'model': 'gem-model', 'contents': 'Hello ==SELECT_FILE_INSTRUCTIONS==', 'config': {}}
|
|
526
|
-
req = DummyRequest(headers=headers, method='POST', json_data=json_params)
|
|
527
|
-
|
|
528
|
-
# Fake client to capture generate_content params
|
|
529
|
-
class FakeModels:
|
|
530
|
-
last_params = None
|
|
531
|
-
def generate_content(self, **params):
|
|
532
|
-
FakeModels.last_params = params
|
|
533
|
-
class FakeResp:
|
|
534
|
-
def to_json_dict(self_inner):
|
|
535
|
-
return {'result': 'ok'}
|
|
536
|
-
@property
|
|
537
|
-
def usage_metadata(self_inner):
|
|
538
|
-
return types.SimpleNamespace(prompt_token_count=1, total_token_count=2)
|
|
539
|
-
return FakeResp()
|
|
540
|
-
|
|
541
|
-
class FakeClient2:
|
|
542
|
-
def __init__(self, api_key):
|
|
543
|
-
self.api_key = api_key
|
|
544
|
-
self.models = FakeModels()
|
|
545
|
-
|
|
546
|
-
with patch.object(_gemini, 'validate_auth_key', return_value=True), \
|
|
547
|
-
patch.object(_gemini, 'verify_firebase_token', return_value={}), \
|
|
548
|
-
patch.object(_gemini, 'get_api_key', return_value='GEMINI-KEY'), \
|
|
549
|
-
patch.object(_gemini.genai, 'Client', FakeClient2):
|
|
550
|
-
resp = _gemini._gemini_proxy(req)
|
|
551
|
-
|
|
552
|
-
payload = _parse_response(resp)
|
|
553
|
-
assert resp.status_code == 200
|
|
554
|
-
assert payload['success'] is True
|
|
555
|
-
assert FakeModels.last_params is not None
|
|
556
|
-
# contents might be passed as string or list depending on implementation; check string presence
|
|
557
|
-
assert ('Some instructions for selecting files' in str(FakeModels.last_params.get('contents'))) or ('files in my codebase' in str(FakeModels.last_params.get('contents')))
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import sys
|
|
3
|
-
import importlib.util
|
|
4
|
-
import types
|
|
5
|
-
|
|
6
|
-
# Ensure the functions/ directory is importable as a top-level module location
|
|
7
|
-
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
|
|
8
|
-
FUNCTIONS_DIR = os.path.join(PROJECT_ROOT, 'functions')
|
|
9
|
-
if FUNCTIONS_DIR not in sys.path:
|
|
10
|
-
sys.path.insert(0, FUNCTIONS_DIR)
|
|
11
|
-
|
|
12
|
-
# Load the keyword_map module from the v1_02 package
|
|
13
|
-
repo_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
|
|
14
|
-
functions_root = os.path.join(repo_root, 'functions')
|
|
15
|
-
module_path = os.path.join(functions_root, 'api_v1_02', 'replace_keywords.py')
|
|
16
|
-
spec = importlib.util.spec_from_file_location('api_v1_02.replace_keywords', module_path)
|
|
17
|
-
_replace_keywords = importlib.util.module_from_spec(spec)
|
|
18
|
-
spec.loader.exec_module(_replace_keywords)
|
|
19
|
-
|
|
20
|
-
replace_keywords = _replace_keywords.replace_keywords
|
|
21
|
-
KEYWORD_MAP = _replace_keywords.KEYWORD_MAP
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def test_recursive_replacement_nested_structures():
|
|
25
|
-
obj = {
|
|
26
|
-
'input': 'Hello ' + list(KEYWORD_MAP.keys())[0] + ' world',
|
|
27
|
-
'messages': [
|
|
28
|
-
{'content': 'First ' + list(KEYWORD_MAP.keys())[0] + ' end'},
|
|
29
|
-
{'content': 'no change'}
|
|
30
|
-
],
|
|
31
|
-
'nested': {'list': ['prefix ' + list(KEYWORD_MAP.keys())[0] + ' suffix', 123]},
|
|
32
|
-
'tuple': ('a ' + list(KEYWORD_MAP.keys())[0] + ' b',),
|
|
33
|
-
'obj': types.SimpleNamespace(text=list(KEYWORD_MAP.keys())[0] + ' inside', number=7)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
result = replace_keywords(obj)
|
|
37
|
-
|
|
38
|
-
expected_replacement = list(KEYWORD_MAP.values())[0]
|
|
39
|
-
assert expected_replacement in result['input']
|
|
40
|
-
assert expected_replacement in result['messages'][0]['content']
|
|
41
|
-
assert expected_replacement in result['nested']['list'][0]
|
|
42
|
-
assert expected_replacement in result['tuple'][0]
|
|
43
|
-
assert expected_replacement in result['obj'].text
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def test_multiple_occurrences_replaced_everywhere():
|
|
47
|
-
key = list(KEYWORD_MAP.keys())[0]
|
|
48
|
-
val = list(KEYWORD_MAP.values())[0]
|
|
49
|
-
s = f"{key} and {key} again"
|
|
50
|
-
out = replace_keywords(s)
|
|
51
|
-
assert out == f"{val} and {val} again"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def test_case_sensitivity_no_match_for_different_case():
|
|
55
|
-
key = list(KEYWORD_MAP.keys())[0]
|
|
56
|
-
lower_key = key.lower()
|
|
57
|
-
s = f"This {lower_key} should remain"
|
|
58
|
-
out = replace_keywords(s)
|
|
59
|
-
assert out == s
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
def test_unknown_keywords_left_unchanged():
|
|
63
|
-
s = 'This contains ==UNKNOWN_KEYWORD== and should remain.'
|
|
64
|
-
out = replace_keywords(s)
|
|
65
|
-
assert out == s
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def test_non_string_values_unchanged():
|
|
69
|
-
data = {'n': 42, 'f': 3.14, 'b': True, 'none': None}
|
|
70
|
-
out = replace_keywords(data)
|
|
71
|
-
assert out['n'] == 42
|
|
72
|
-
assert out['f'] == 3.14
|
|
73
|
-
assert out['b'] is True
|
|
74
|
-
assert out['none'] is None
|
tests/functions/test_auth.py
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import importlib
|
|
2
|
-
from cryptography.fernet import Fernet
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def test_validate_auth_key_returns_true_for_valid_token():
|
|
6
|
-
"""Encrypt the known AUTH_KEY with the module's FERNET_KEY and verify validation passes."""
|
|
7
|
-
auth = importlib.import_module('auth')
|
|
8
|
-
cipher = Fernet(auth.FERNET_KEY)
|
|
9
|
-
token = cipher.encrypt(auth.AUTH_KEY.encode()).decode('utf-8')
|
|
10
|
-
assert auth.validate_auth_key(token) is True
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def test_validate_auth_key_returns_false_for_invalid_token_string():
|
|
14
|
-
"""Passing a non-Fernet string should return False rather than raise."""
|
|
15
|
-
auth = importlib.import_module('auth')
|
|
16
|
-
assert auth.validate_auth_key('not-a-token') is False
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def test_validate_auth_key_returns_false_for_wrong_plaintext():
|
|
20
|
-
"""Encrypting a different plaintext with the correct key should not validate."""
|
|
21
|
-
auth = importlib.import_module('auth')
|
|
22
|
-
cipher = Fernet(auth.FERNET_KEY)
|
|
23
|
-
token = cipher.encrypt(b'WRONG').decode('utf-8')
|
|
24
|
-
assert auth.validate_auth_key(token) is False
|