lean-explore 0.2.0__py3-none-any.whl → 0.2.2__py3-none-any.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.
- lean_explore/cli/config_utils.py +144 -71
- {lean_explore-0.2.0.dist-info → lean_explore-0.2.2.dist-info}/METADATA +2 -4
- {lean_explore-0.2.0.dist-info → lean_explore-0.2.2.dist-info}/RECORD +7 -7
- {lean_explore-0.2.0.dist-info → lean_explore-0.2.2.dist-info}/WHEEL +0 -0
- {lean_explore-0.2.0.dist-info → lean_explore-0.2.2.dist-info}/entry_points.txt +0 -0
- {lean_explore-0.2.0.dist-info → lean_explore-0.2.2.dist-info}/licenses/LICENSE +0 -0
- {lean_explore-0.2.0.dist-info → lean_explore-0.2.2.dist-info}/top_level.txt +0 -0
lean_explore/cli/config_utils.py
CHANGED
|
@@ -6,7 +6,8 @@ This module provides functions to save and load user-specific settings,
|
|
|
6
6
|
such as API keys for Lean Explore and OpenAI, from a configuration
|
|
7
7
|
file stored in the user's home directory. It handles file creation,
|
|
8
8
|
parsing, and sets secure permissions for files containing sensitive
|
|
9
|
-
information.
|
|
9
|
+
information. It also supports loading API keys from environment
|
|
10
|
+
variables as a fallback if they are not found in the configuration file.
|
|
10
11
|
"""
|
|
11
12
|
|
|
12
13
|
import logging
|
|
@@ -23,12 +24,14 @@ _APP_CONFIG_DIR_NAME: str = "leanexplore"
|
|
|
23
24
|
_CONFIG_FILENAME: str = "config.toml"
|
|
24
25
|
|
|
25
26
|
# Define keys for Lean Explore API section
|
|
26
|
-
_LEAN_EXPLORE_API_SECTION_NAME: str = "lean_explore_api"
|
|
27
|
+
_LEAN_EXPLORE_API_SECTION_NAME: str = "lean_explore_api"
|
|
27
28
|
_LEAN_EXPLORE_API_KEY_NAME: str = "key"
|
|
29
|
+
_LEAN_EXPLORE_API_KEY_ENV_VAR: str = "LEANEXPLORE_API_KEY"
|
|
28
30
|
|
|
29
31
|
# Define keys for OpenAI API section
|
|
30
32
|
_OPENAI_API_SECTION_NAME: str = "openai"
|
|
31
|
-
_OPENAI_API_KEY_NAME: str = "api_key"
|
|
33
|
+
_OPENAI_API_KEY_NAME: str = "api_key"
|
|
34
|
+
_OPENAI_API_KEY_ENV_VAR: str = "OPENAI_API_KEY"
|
|
32
35
|
|
|
33
36
|
|
|
34
37
|
def get_config_file_path() -> pathlib.Path:
|
|
@@ -83,7 +86,6 @@ def _load_config_data(config_file_path: pathlib.Path) -> Dict[str, Any]:
|
|
|
83
86
|
"Configuration file %s is corrupted. Treating as empty.",
|
|
84
87
|
config_file_path,
|
|
85
88
|
)
|
|
86
|
-
# Potentially back up corrupted file before returning empty
|
|
87
89
|
except Exception as e:
|
|
88
90
|
logger.error(
|
|
89
91
|
"Error reading existing config file %s: %s",
|
|
@@ -91,7 +93,6 @@ def _load_config_data(config_file_path: pathlib.Path) -> Dict[str, Any]:
|
|
|
91
93
|
e,
|
|
92
94
|
exc_info=True,
|
|
93
95
|
)
|
|
94
|
-
# Decide if to proceed with empty or raise further
|
|
95
96
|
return config_data
|
|
96
97
|
|
|
97
98
|
|
|
@@ -162,9 +163,7 @@ def save_api_key(api_key: str) -> bool:
|
|
|
162
163
|
if _save_config_data(config_file_path, config_data):
|
|
163
164
|
logger.info("Lean Explore API key saved to %s", config_file_path)
|
|
164
165
|
return True
|
|
165
|
-
except
|
|
166
|
-
Exception
|
|
167
|
-
) as e: # Catch any exception from _ensure_config_dir_exists or broad issues
|
|
166
|
+
except Exception as e:
|
|
168
167
|
logger.error(
|
|
169
168
|
"General error during Lean Explore API key saving process: %s",
|
|
170
169
|
e,
|
|
@@ -174,50 +173,86 @@ def save_api_key(api_key: str) -> bool:
|
|
|
174
173
|
|
|
175
174
|
|
|
176
175
|
def load_api_key() -> Optional[str]:
|
|
177
|
-
"""Loads the Lean Explore API key
|
|
176
|
+
"""Loads the Lean Explore API key.
|
|
177
|
+
|
|
178
|
+
It first checks the user's configuration file (typically
|
|
179
|
+
~/.config/leanexplore/config.toml under the section
|
|
180
|
+
`lean_explore_api` with key `key`). If a valid, non-empty API key
|
|
181
|
+
is found there, it is returned.
|
|
182
|
+
|
|
183
|
+
If the API key is not found in the configuration file, is empty,
|
|
184
|
+
or is not a string, this function then checks the environment
|
|
185
|
+
variable `LEAN_EXPLORE_API_KEY`. If this environment variable is
|
|
186
|
+
set to a non-empty string, its value is returned.
|
|
187
|
+
|
|
188
|
+
If the API key is not found or is invalid in both locations,
|
|
189
|
+
None is returned.
|
|
178
190
|
|
|
179
191
|
Returns:
|
|
180
192
|
Optional[str]: The Lean Explore API key string if found and valid,
|
|
181
193
|
otherwise None.
|
|
182
194
|
"""
|
|
183
195
|
config_file_path = get_config_file_path()
|
|
184
|
-
if not config_file_path.exists() or not config_file_path.is_file():
|
|
185
|
-
logger.debug(
|
|
186
|
-
"Configuration file not found at %s for Lean Explore API key.",
|
|
187
|
-
config_file_path,
|
|
188
|
-
)
|
|
189
|
-
return None
|
|
190
196
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
if api_key and isinstance(api_key, str):
|
|
198
|
-
logger.debug(
|
|
199
|
-
"Lean Explore API key loaded successfully from %s", config_file_path
|
|
200
|
-
)
|
|
201
|
-
return api_key
|
|
202
|
-
elif api_key: # Found but not a string
|
|
203
|
-
logger.warning(
|
|
204
|
-
"Lean Explore API key found in %s but is not a valid string.",
|
|
205
|
-
config_file_path,
|
|
197
|
+
# 1. Try loading from config file
|
|
198
|
+
if config_file_path.exists() and config_file_path.is_file():
|
|
199
|
+
try:
|
|
200
|
+
config_data = _load_config_data(config_file_path)
|
|
201
|
+
key_value = config_data.get(_LEAN_EXPLORE_API_SECTION_NAME, {}).get(
|
|
202
|
+
_LEAN_EXPLORE_API_KEY_NAME
|
|
206
203
|
)
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
204
|
+
|
|
205
|
+
if isinstance(key_value, str) and key_value: # Non-empty string
|
|
206
|
+
logger.debug(
|
|
207
|
+
"Lean Explore API key loaded from configuration file %s",
|
|
208
|
+
config_file_path,
|
|
209
|
+
)
|
|
210
|
+
return key_value
|
|
211
|
+
elif key_value is not None: # Present but not a valid non-empty string
|
|
212
|
+
logger.warning(
|
|
213
|
+
"Lean Explore API key found in %s but is not a valid "
|
|
214
|
+
"non-empty string. "
|
|
215
|
+
"Will check environment variable %s.",
|
|
216
|
+
config_file_path,
|
|
217
|
+
_LEAN_EXPLORE_API_KEY_ENV_VAR,
|
|
218
|
+
)
|
|
219
|
+
except Exception as e: # Catch unexpected errors during config processing
|
|
220
|
+
logger.error(
|
|
221
|
+
"Error processing configuration file %s for Lean Explore API key: %s. "
|
|
222
|
+
"Will check environment variable %s.",
|
|
212
223
|
config_file_path,
|
|
224
|
+
e,
|
|
225
|
+
_LEAN_EXPLORE_API_KEY_ENV_VAR,
|
|
226
|
+
exc_info=True,
|
|
213
227
|
)
|
|
214
|
-
|
|
215
|
-
logger.
|
|
216
|
-
"
|
|
228
|
+
else:
|
|
229
|
+
logger.debug(
|
|
230
|
+
"Configuration file %s not found. Will check environment "
|
|
231
|
+
"variable %s for Lean Explore API key.",
|
|
217
232
|
config_file_path,
|
|
218
|
-
|
|
219
|
-
exc_info=True,
|
|
233
|
+
_LEAN_EXPLORE_API_KEY_ENV_VAR,
|
|
220
234
|
)
|
|
235
|
+
|
|
236
|
+
# 2. Try loading from environment variable
|
|
237
|
+
api_key_from_env = os.getenv(_LEAN_EXPLORE_API_KEY_ENV_VAR)
|
|
238
|
+
|
|
239
|
+
if isinstance(api_key_from_env, str) and api_key_from_env: # Non-empty string
|
|
240
|
+
logger.debug(
|
|
241
|
+
"Lean Explore API key loaded from environment variable %s",
|
|
242
|
+
_LEAN_EXPLORE_API_KEY_ENV_VAR,
|
|
243
|
+
)
|
|
244
|
+
return api_key_from_env
|
|
245
|
+
elif api_key_from_env is not None: # Env var exists but is empty string
|
|
246
|
+
logger.debug(
|
|
247
|
+
"Environment variable %s for Lean Explore API key is set but empty.",
|
|
248
|
+
_LEAN_EXPLORE_API_KEY_ENV_VAR,
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
logger.debug(
|
|
252
|
+
"Lean Explore API key not found in configuration file or "
|
|
253
|
+
"valid in environment variable %s.",
|
|
254
|
+
_LEAN_EXPLORE_API_KEY_ENV_VAR,
|
|
255
|
+
)
|
|
221
256
|
return None
|
|
222
257
|
|
|
223
258
|
|
|
@@ -262,7 +297,7 @@ def delete_api_key() -> bool:
|
|
|
262
297
|
"Lean Explore API key not found in %s, no deletion performed.",
|
|
263
298
|
config_file_path,
|
|
264
299
|
)
|
|
265
|
-
return True
|
|
300
|
+
return True
|
|
266
301
|
|
|
267
302
|
except Exception as e:
|
|
268
303
|
logger.error(
|
|
@@ -316,46 +351,84 @@ def save_openai_api_key(api_key: str) -> bool:
|
|
|
316
351
|
|
|
317
352
|
|
|
318
353
|
def load_openai_api_key() -> Optional[str]:
|
|
319
|
-
"""Loads the OpenAI API key
|
|
354
|
+
"""Loads the OpenAI API key.
|
|
355
|
+
|
|
356
|
+
It first checks the user's configuration file (typically
|
|
357
|
+
~/.config/leanexplore/config.toml under the section
|
|
358
|
+
`openai` with key `api_key`). If a valid, non-empty API key
|
|
359
|
+
is found there, it is returned.
|
|
360
|
+
|
|
361
|
+
If the API key is not found in the configuration file, is empty,
|
|
362
|
+
or is not a string, this function then checks the environment
|
|
363
|
+
variable `OPENAI_API_KEY`. If this environment variable is
|
|
364
|
+
set to a non-empty string, its value is returned.
|
|
365
|
+
|
|
366
|
+
If the API key is not found or is invalid in both locations,
|
|
367
|
+
None is returned.
|
|
320
368
|
|
|
321
369
|
Returns:
|
|
322
370
|
Optional[str]: The OpenAI API key string if found and valid, otherwise None.
|
|
323
371
|
"""
|
|
324
372
|
config_file_path = get_config_file_path()
|
|
325
|
-
if not config_file_path.exists() or not config_file_path.is_file():
|
|
326
|
-
logger.debug(
|
|
327
|
-
"Configuration file not found at %s for OpenAI API key.", config_file_path
|
|
328
|
-
)
|
|
329
|
-
return None
|
|
330
373
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
if api_key and isinstance(api_key, str):
|
|
338
|
-
logger.debug("OpenAI API key loaded successfully from %s", config_file_path)
|
|
339
|
-
return api_key
|
|
340
|
-
elif api_key: # Found but not a string
|
|
341
|
-
logger.warning(
|
|
342
|
-
"OpenAI API key found in %s but is not a valid string.",
|
|
343
|
-
config_file_path,
|
|
374
|
+
# 1. Try loading from config file
|
|
375
|
+
if config_file_path.exists() and config_file_path.is_file():
|
|
376
|
+
try:
|
|
377
|
+
config_data = _load_config_data(config_file_path)
|
|
378
|
+
key_value = config_data.get(_OPENAI_API_SECTION_NAME, {}).get(
|
|
379
|
+
_OPENAI_API_KEY_NAME
|
|
344
380
|
)
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
381
|
+
|
|
382
|
+
if isinstance(key_value, str) and key_value: # Non-empty string
|
|
383
|
+
logger.debug(
|
|
384
|
+
"OpenAI API key loaded from configuration file %s",
|
|
385
|
+
config_file_path,
|
|
386
|
+
)
|
|
387
|
+
return key_value
|
|
388
|
+
elif key_value is not None: # Present but not a valid non-empty string
|
|
389
|
+
logger.warning(
|
|
390
|
+
"OpenAI API key found in %s but is not a valid non-empty string. "
|
|
391
|
+
"Will check environment variable %s.",
|
|
392
|
+
config_file_path,
|
|
393
|
+
_OPENAI_API_KEY_ENV_VAR,
|
|
394
|
+
)
|
|
395
|
+
except Exception as e: # Catch unexpected errors during config processing
|
|
396
|
+
logger.error(
|
|
397
|
+
"Error processing configuration file %s for OpenAI API key: %s. "
|
|
398
|
+
"Will check environment variable %s.",
|
|
350
399
|
config_file_path,
|
|
400
|
+
e,
|
|
401
|
+
_OPENAI_API_KEY_ENV_VAR,
|
|
402
|
+
exc_info=True,
|
|
351
403
|
)
|
|
352
|
-
|
|
353
|
-
logger.
|
|
354
|
-
"
|
|
404
|
+
else:
|
|
405
|
+
logger.debug(
|
|
406
|
+
"Configuration file %s not found. Will check environment "
|
|
407
|
+
"variable %s for OpenAI API key.",
|
|
355
408
|
config_file_path,
|
|
356
|
-
|
|
357
|
-
exc_info=True,
|
|
409
|
+
_OPENAI_API_KEY_ENV_VAR,
|
|
358
410
|
)
|
|
411
|
+
|
|
412
|
+
# 2. Try loading from environment variable
|
|
413
|
+
api_key_from_env = os.getenv(_OPENAI_API_KEY_ENV_VAR)
|
|
414
|
+
|
|
415
|
+
if isinstance(api_key_from_env, str) and api_key_from_env: # Non-empty string
|
|
416
|
+
logger.debug(
|
|
417
|
+
"OpenAI API key loaded from environment variable %s",
|
|
418
|
+
_OPENAI_API_KEY_ENV_VAR,
|
|
419
|
+
)
|
|
420
|
+
return api_key_from_env
|
|
421
|
+
elif api_key_from_env is not None: # Env var exists but is empty string
|
|
422
|
+
logger.debug(
|
|
423
|
+
"Environment variable %s for OpenAI API key is set but empty.",
|
|
424
|
+
_OPENAI_API_KEY_ENV_VAR,
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
logger.debug(
|
|
428
|
+
"OpenAI API key not found in configuration file or valid in "
|
|
429
|
+
"environment variable %s.",
|
|
430
|
+
_OPENAI_API_KEY_ENV_VAR,
|
|
431
|
+
)
|
|
359
432
|
return None
|
|
360
433
|
|
|
361
434
|
|
|
@@ -396,7 +469,7 @@ def delete_openai_api_key() -> bool:
|
|
|
396
469
|
"OpenAI API key not found in %s, no deletion performed.",
|
|
397
470
|
config_file_path,
|
|
398
471
|
)
|
|
399
|
-
return True
|
|
472
|
+
return True
|
|
400
473
|
|
|
401
474
|
except Exception as e:
|
|
402
475
|
logger.error(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lean-explore
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: A project to explore and rank Lean mathematical declarations.
|
|
5
5
|
Author-email: Justin Asher <justinchadwickasher@gmail.com>
|
|
6
6
|
License: Apache License
|
|
@@ -213,15 +213,13 @@ Classifier: Intended Audience :: Developers
|
|
|
213
213
|
Classifier: Intended Audience :: Science/Research
|
|
214
214
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
215
215
|
Classifier: Programming Language :: Python :: 3
|
|
216
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
217
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
218
216
|
Classifier: Programming Language :: Python :: 3.10
|
|
219
217
|
Classifier: Programming Language :: Python :: 3.11
|
|
220
218
|
Classifier: Programming Language :: Python :: 3.12
|
|
221
219
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
222
220
|
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
223
221
|
Classifier: Topic :: Text Processing :: Indexing
|
|
224
|
-
Requires-Python: >=3.
|
|
222
|
+
Requires-Python: >=3.10
|
|
225
223
|
Description-Content-Type: text/markdown
|
|
226
224
|
License-File: LICENSE
|
|
227
225
|
Requires-Dist: sqlalchemy>=2.0
|
|
@@ -4,7 +4,7 @@ lean_explore/api/__init__.py,sha256=LK4g9wj7jCilTUfQcdQAxDf3F2GjMwzQZJYgnQ8ciGo,
|
|
|
4
4
|
lean_explore/api/client.py,sha256=AgZG7pUY53Tl1WOhJgUdT0yxa_O1sHsals0pnjRD-Pc,4839
|
|
5
5
|
lean_explore/cli/__init__.py,sha256=LK4g9wj7jCilTUfQcdQAxDf3F2GjMwzQZJYgnQ8ciGo,38
|
|
6
6
|
lean_explore/cli/agent.py,sha256=jf1ebnViAqtKcZAGArqBf9YKHPbsOTpffOXr0Cd2M3Q,29933
|
|
7
|
-
lean_explore/cli/config_utils.py,sha256=
|
|
7
|
+
lean_explore/cli/config_utils.py,sha256=RyIaDNP1UpUQZoy7HfaZ_JOXUgtzUP51Zrq_s6q7urY,16639
|
|
8
8
|
lean_explore/cli/data_commands.py,sha256=mTBqFU7-fF4ZBGzCmNawZA_eHy0jyEMLlBEDEBXpxwY,21462
|
|
9
9
|
lean_explore/cli/main.py,sha256=ZdbXy8x2VQ--JARqJMa9iFnrOhOCLcVgjpWhXkxj80o,24323
|
|
10
10
|
lean_explore/local/__init__.py,sha256=LK4g9wj7jCilTUfQcdQAxDf3F2GjMwzQZJYgnQ8ciGo,38
|
|
@@ -18,9 +18,9 @@ lean_explore/shared/__init__.py,sha256=LK4g9wj7jCilTUfQcdQAxDf3F2GjMwzQZJYgnQ8ci
|
|
|
18
18
|
lean_explore/shared/models/__init__.py,sha256=LK4g9wj7jCilTUfQcdQAxDf3F2GjMwzQZJYgnQ8ciGo,38
|
|
19
19
|
lean_explore/shared/models/api.py,sha256=jejNDpgj-cu0KZTqkuOjM0useN4EvhvNB19lFFAOV94,4635
|
|
20
20
|
lean_explore/shared/models/db.py,sha256=JYfIBnPrHZO2j7gHAVMlw9WSqVC2NinCG5KuBzdQWyk,16099
|
|
21
|
-
lean_explore-0.2.
|
|
22
|
-
lean_explore-0.2.
|
|
23
|
-
lean_explore-0.2.
|
|
24
|
-
lean_explore-0.2.
|
|
25
|
-
lean_explore-0.2.
|
|
26
|
-
lean_explore-0.2.
|
|
21
|
+
lean_explore-0.2.2.dist-info/licenses/LICENSE,sha256=l4QLw1kIvEOjUktmmKm4dycK1E249Qs2s2AQTYbMXpY,11354
|
|
22
|
+
lean_explore-0.2.2.dist-info/METADATA,sha256=SlZZqUVDTwZmx_LftmAb3yobtTbZMvFfeTQYB1Hnuvs,15512
|
|
23
|
+
lean_explore-0.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
24
|
+
lean_explore-0.2.2.dist-info/entry_points.txt,sha256=JXl2Mo3BRX4jAU-Nxg_CWJR790pB_oi5qnt3Pv5iZnk,58
|
|
25
|
+
lean_explore-0.2.2.dist-info/top_level.txt,sha256=h51BKWrFvB7iym-IlaNAAHX5MZfA8Gmg-aDuXGo0fQ8,13
|
|
26
|
+
lean_explore-0.2.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|