edsl 0.1.39.dev3__py3-none-any.whl → 0.1.39.dev4__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.
- edsl/Base.py +413 -332
- edsl/BaseDiff.py +260 -260
- edsl/TemplateLoader.py +24 -24
- edsl/__init__.py +57 -49
- edsl/__version__.py +1 -1
- edsl/agents/Agent.py +1071 -867
- edsl/agents/AgentList.py +551 -413
- edsl/agents/Invigilator.py +284 -233
- edsl/agents/InvigilatorBase.py +257 -270
- edsl/agents/PromptConstructor.py +272 -354
- edsl/agents/QuestionInstructionPromptBuilder.py +128 -0
- edsl/agents/QuestionTemplateReplacementsBuilder.py +137 -0
- edsl/agents/__init__.py +2 -3
- edsl/agents/descriptors.py +99 -99
- edsl/agents/prompt_helpers.py +129 -129
- edsl/agents/question_option_processor.py +172 -0
- edsl/auto/AutoStudy.py +130 -117
- edsl/auto/StageBase.py +243 -230
- edsl/auto/StageGenerateSurvey.py +178 -178
- edsl/auto/StageLabelQuestions.py +125 -125
- edsl/auto/StagePersona.py +61 -61
- edsl/auto/StagePersonaDimensionValueRanges.py +88 -88
- edsl/auto/StagePersonaDimensionValues.py +74 -74
- edsl/auto/StagePersonaDimensions.py +69 -69
- edsl/auto/StageQuestions.py +74 -73
- edsl/auto/SurveyCreatorPipeline.py +21 -21
- edsl/auto/utilities.py +218 -224
- edsl/base/Base.py +279 -279
- edsl/config.py +177 -157
- edsl/conversation/Conversation.py +290 -290
- edsl/conversation/car_buying.py +59 -58
- edsl/conversation/chips.py +95 -95
- edsl/conversation/mug_negotiation.py +81 -81
- edsl/conversation/next_speaker_utilities.py +93 -93
- edsl/coop/CoopFunctionsMixin.py +15 -0
- edsl/coop/ExpectedParrotKeyHandler.py +125 -0
- edsl/coop/PriceFetcher.py +54 -54
- edsl/coop/__init__.py +2 -2
- edsl/coop/coop.py +1106 -1028
- edsl/coop/utils.py +131 -131
- edsl/data/Cache.py +573 -555
- edsl/data/CacheEntry.py +230 -233
- edsl/data/CacheHandler.py +168 -149
- edsl/data/RemoteCacheSync.py +186 -78
- edsl/data/SQLiteDict.py +292 -292
- edsl/data/__init__.py +5 -4
- edsl/data/hack.py +10 -0
- edsl/data/orm.py +10 -10
- edsl/data_transfer_models.py +74 -73
- edsl/enums.py +202 -175
- edsl/exceptions/BaseException.py +21 -21
- edsl/exceptions/__init__.py +54 -54
- edsl/exceptions/agents.py +54 -42
- edsl/exceptions/cache.py +5 -5
- edsl/exceptions/configuration.py +16 -16
- edsl/exceptions/coop.py +10 -10
- edsl/exceptions/data.py +14 -14
- edsl/exceptions/general.py +34 -34
- edsl/exceptions/inference_services.py +5 -0
- edsl/exceptions/jobs.py +33 -33
- edsl/exceptions/language_models.py +63 -63
- edsl/exceptions/prompts.py +15 -15
- edsl/exceptions/questions.py +109 -91
- edsl/exceptions/results.py +29 -29
- edsl/exceptions/scenarios.py +29 -22
- edsl/exceptions/surveys.py +37 -37
- edsl/inference_services/AnthropicService.py +106 -87
- edsl/inference_services/AvailableModelCacheHandler.py +184 -0
- edsl/inference_services/AvailableModelFetcher.py +215 -0
- edsl/inference_services/AwsBedrock.py +118 -120
- edsl/inference_services/AzureAI.py +215 -217
- edsl/inference_services/DeepInfraService.py +18 -18
- edsl/inference_services/GoogleService.py +143 -148
- edsl/inference_services/GroqService.py +20 -20
- edsl/inference_services/InferenceServiceABC.py +80 -147
- edsl/inference_services/InferenceServicesCollection.py +138 -97
- edsl/inference_services/MistralAIService.py +120 -123
- edsl/inference_services/OllamaService.py +18 -18
- edsl/inference_services/OpenAIService.py +236 -224
- edsl/inference_services/PerplexityService.py +160 -163
- edsl/inference_services/ServiceAvailability.py +135 -0
- edsl/inference_services/TestService.py +90 -89
- edsl/inference_services/TogetherAIService.py +172 -170
- edsl/inference_services/data_structures.py +134 -0
- edsl/inference_services/models_available_cache.py +118 -118
- edsl/inference_services/rate_limits_cache.py +25 -25
- edsl/inference_services/registry.py +41 -41
- edsl/inference_services/write_available.py +10 -10
- edsl/jobs/AnswerQuestionFunctionConstructor.py +223 -0
- edsl/jobs/Answers.py +43 -56
- edsl/jobs/FetchInvigilator.py +47 -0
- edsl/jobs/InterviewTaskManager.py +98 -0
- edsl/jobs/InterviewsConstructor.py +50 -0
- edsl/jobs/Jobs.py +823 -898
- edsl/jobs/JobsChecks.py +172 -147
- edsl/jobs/JobsComponentConstructor.py +189 -0
- edsl/jobs/JobsPrompts.py +270 -268
- edsl/jobs/JobsRemoteInferenceHandler.py +311 -239
- edsl/jobs/JobsRemoteInferenceLogger.py +239 -0
- edsl/jobs/RequestTokenEstimator.py +30 -0
- edsl/jobs/__init__.py +1 -1
- edsl/jobs/async_interview_runner.py +138 -0
- edsl/jobs/buckets/BucketCollection.py +104 -63
- edsl/jobs/buckets/ModelBuckets.py +65 -65
- edsl/jobs/buckets/TokenBucket.py +283 -251
- edsl/jobs/buckets/TokenBucketAPI.py +211 -0
- edsl/jobs/buckets/TokenBucketClient.py +191 -0
- edsl/jobs/check_survey_scenario_compatibility.py +85 -0
- edsl/jobs/data_structures.py +120 -0
- edsl/jobs/decorators.py +35 -0
- edsl/jobs/interviews/Interview.py +396 -661
- edsl/jobs/interviews/InterviewExceptionCollection.py +99 -99
- edsl/jobs/interviews/InterviewExceptionEntry.py +186 -186
- edsl/jobs/interviews/InterviewStatistic.py +63 -63
- edsl/jobs/interviews/InterviewStatisticsCollection.py +25 -25
- edsl/jobs/interviews/InterviewStatusDictionary.py +78 -78
- edsl/jobs/interviews/InterviewStatusLog.py +92 -92
- edsl/jobs/interviews/ReportErrors.py +66 -66
- edsl/jobs/interviews/interview_status_enum.py +9 -9
- edsl/jobs/jobs_status_enums.py +9 -0
- edsl/jobs/loggers/HTMLTableJobLogger.py +304 -0
- edsl/jobs/results_exceptions_handler.py +98 -0
- edsl/jobs/runners/JobsRunnerAsyncio.py +151 -466
- edsl/jobs/runners/JobsRunnerStatus.py +297 -330
- edsl/jobs/tasks/QuestionTaskCreator.py +244 -242
- edsl/jobs/tasks/TaskCreators.py +64 -64
- edsl/jobs/tasks/TaskHistory.py +470 -450
- edsl/jobs/tasks/TaskStatusLog.py +23 -23
- edsl/jobs/tasks/task_status_enum.py +161 -163
- edsl/jobs/tokens/InterviewTokenUsage.py +27 -27
- edsl/jobs/tokens/TokenUsage.py +34 -34
- edsl/language_models/ComputeCost.py +63 -0
- edsl/language_models/LanguageModel.py +626 -668
- edsl/language_models/ModelList.py +164 -155
- edsl/language_models/PriceManager.py +127 -0
- edsl/language_models/RawResponseHandler.py +106 -0
- edsl/language_models/RegisterLanguageModelsMeta.py +184 -184
- edsl/language_models/ServiceDataSources.py +0 -0
- edsl/language_models/__init__.py +2 -3
- edsl/language_models/fake_openai_call.py +15 -15
- edsl/language_models/fake_openai_service.py +61 -61
- edsl/language_models/key_management/KeyLookup.py +63 -0
- edsl/language_models/key_management/KeyLookupBuilder.py +273 -0
- edsl/language_models/key_management/KeyLookupCollection.py +38 -0
- edsl/language_models/key_management/__init__.py +0 -0
- edsl/language_models/key_management/models.py +131 -0
- edsl/language_models/model.py +256 -0
- edsl/language_models/repair.py +156 -156
- edsl/language_models/utilities.py +65 -64
- edsl/notebooks/Notebook.py +263 -258
- edsl/notebooks/NotebookToLaTeX.py +142 -0
- edsl/notebooks/__init__.py +1 -1
- edsl/prompts/Prompt.py +352 -362
- edsl/prompts/__init__.py +2 -2
- edsl/questions/ExceptionExplainer.py +77 -0
- edsl/questions/HTMLQuestion.py +103 -0
- edsl/questions/QuestionBase.py +518 -664
- edsl/questions/QuestionBasePromptsMixin.py +221 -217
- edsl/questions/QuestionBudget.py +227 -227
- edsl/questions/QuestionCheckBox.py +359 -359
- edsl/questions/QuestionExtract.py +180 -182
- edsl/questions/QuestionFreeText.py +113 -114
- edsl/questions/QuestionFunctional.py +166 -166
- edsl/questions/QuestionList.py +223 -231
- edsl/questions/QuestionMatrix.py +265 -0
- edsl/questions/QuestionMultipleChoice.py +330 -286
- edsl/questions/QuestionNumerical.py +151 -153
- edsl/questions/QuestionRank.py +314 -324
- edsl/questions/Quick.py +41 -41
- edsl/questions/SimpleAskMixin.py +74 -73
- edsl/questions/__init__.py +27 -26
- edsl/questions/{AnswerValidatorMixin.py → answer_validator_mixin.py} +334 -289
- edsl/questions/compose_questions.py +98 -98
- edsl/questions/data_structures.py +20 -0
- edsl/questions/decorators.py +21 -21
- edsl/questions/derived/QuestionLikertFive.py +76 -76
- edsl/questions/derived/QuestionLinearScale.py +90 -87
- edsl/questions/derived/QuestionTopK.py +93 -93
- edsl/questions/derived/QuestionYesNo.py +82 -82
- edsl/questions/descriptors.py +427 -413
- edsl/questions/loop_processor.py +149 -0
- edsl/questions/prompt_templates/question_budget.jinja +13 -13
- edsl/questions/prompt_templates/question_checkbox.jinja +32 -32
- edsl/questions/prompt_templates/question_extract.jinja +11 -11
- edsl/questions/prompt_templates/question_free_text.jinja +3 -3
- edsl/questions/prompt_templates/question_linear_scale.jinja +11 -11
- edsl/questions/prompt_templates/question_list.jinja +17 -17
- edsl/questions/prompt_templates/question_multiple_choice.jinja +33 -33
- edsl/questions/prompt_templates/question_numerical.jinja +36 -36
- edsl/questions/{QuestionBaseGenMixin.py → question_base_gen_mixin.py} +168 -161
- edsl/questions/question_registry.py +177 -177
- edsl/questions/{RegisterQuestionsMeta.py → register_questions_meta.py} +71 -71
- edsl/questions/{ResponseValidatorABC.py → response_validator_abc.py} +188 -174
- edsl/questions/response_validator_factory.py +34 -0
- edsl/questions/settings.py +12 -12
- edsl/questions/templates/budget/answering_instructions.jinja +7 -7
- edsl/questions/templates/budget/question_presentation.jinja +7 -7
- edsl/questions/templates/checkbox/answering_instructions.jinja +10 -10
- edsl/questions/templates/checkbox/question_presentation.jinja +22 -22
- edsl/questions/templates/extract/answering_instructions.jinja +7 -7
- edsl/questions/templates/likert_five/answering_instructions.jinja +10 -10
- edsl/questions/templates/likert_five/question_presentation.jinja +11 -11
- edsl/questions/templates/linear_scale/answering_instructions.jinja +5 -5
- edsl/questions/templates/linear_scale/question_presentation.jinja +5 -5
- edsl/questions/templates/list/answering_instructions.jinja +3 -3
- edsl/questions/templates/list/question_presentation.jinja +5 -5
- edsl/questions/templates/matrix/__init__.py +1 -0
- edsl/questions/templates/matrix/answering_instructions.jinja +5 -0
- edsl/questions/templates/matrix/question_presentation.jinja +20 -0
- edsl/questions/templates/multiple_choice/answering_instructions.jinja +9 -9
- edsl/questions/templates/multiple_choice/question_presentation.jinja +11 -11
- edsl/questions/templates/numerical/answering_instructions.jinja +6 -6
- edsl/questions/templates/numerical/question_presentation.jinja +6 -6
- edsl/questions/templates/rank/answering_instructions.jinja +11 -11
- edsl/questions/templates/rank/question_presentation.jinja +15 -15
- edsl/questions/templates/top_k/answering_instructions.jinja +8 -8
- edsl/questions/templates/top_k/question_presentation.jinja +22 -22
- edsl/questions/templates/yes_no/answering_instructions.jinja +6 -6
- edsl/questions/templates/yes_no/question_presentation.jinja +11 -11
- edsl/results/CSSParameterizer.py +108 -108
- edsl/results/Dataset.py +587 -424
- edsl/results/DatasetExportMixin.py +594 -731
- edsl/results/DatasetTree.py +295 -275
- edsl/results/MarkdownToDocx.py +122 -0
- edsl/results/MarkdownToPDF.py +111 -0
- edsl/results/Result.py +557 -465
- edsl/results/Results.py +1183 -1165
- edsl/results/ResultsExportMixin.py +45 -43
- edsl/results/ResultsGGMixin.py +121 -121
- edsl/results/TableDisplay.py +125 -198
- edsl/results/TextEditor.py +50 -0
- edsl/results/__init__.py +2 -2
- edsl/results/file_exports.py +252 -0
- edsl/results/{ResultsFetchMixin.py → results_fetch_mixin.py} +33 -33
- edsl/results/{Selector.py → results_selector.py} +145 -135
- edsl/results/{ResultsToolsMixin.py → results_tools_mixin.py} +98 -98
- edsl/results/smart_objects.py +96 -0
- edsl/results/table_data_class.py +12 -0
- edsl/results/table_display.css +77 -77
- edsl/results/table_renderers.py +118 -0
- edsl/results/tree_explore.py +115 -115
- edsl/scenarios/ConstructDownloadLink.py +109 -0
- edsl/scenarios/DocumentChunker.py +102 -0
- edsl/scenarios/DocxScenario.py +16 -0
- edsl/scenarios/FileStore.py +511 -632
- edsl/scenarios/PdfExtractor.py +40 -0
- edsl/scenarios/Scenario.py +498 -601
- edsl/scenarios/ScenarioHtmlMixin.py +65 -64
- edsl/scenarios/ScenarioList.py +1458 -1287
- edsl/scenarios/ScenarioListExportMixin.py +45 -52
- edsl/scenarios/ScenarioListPdfMixin.py +239 -261
- edsl/scenarios/__init__.py +3 -4
- edsl/scenarios/directory_scanner.py +96 -0
- edsl/scenarios/file_methods.py +85 -0
- edsl/scenarios/handlers/__init__.py +13 -0
- edsl/scenarios/handlers/csv.py +38 -0
- edsl/scenarios/handlers/docx.py +76 -0
- edsl/scenarios/handlers/html.py +37 -0
- edsl/scenarios/handlers/json.py +111 -0
- edsl/scenarios/handlers/latex.py +5 -0
- edsl/scenarios/handlers/md.py +51 -0
- edsl/scenarios/handlers/pdf.py +68 -0
- edsl/scenarios/handlers/png.py +39 -0
- edsl/scenarios/handlers/pptx.py +105 -0
- edsl/scenarios/handlers/py.py +294 -0
- edsl/scenarios/handlers/sql.py +313 -0
- edsl/scenarios/handlers/sqlite.py +149 -0
- edsl/scenarios/handlers/txt.py +33 -0
- edsl/scenarios/{ScenarioJoin.py → scenario_join.py} +131 -127
- edsl/scenarios/scenario_selector.py +156 -0
- edsl/shared.py +1 -1
- edsl/study/ObjectEntry.py +173 -173
- edsl/study/ProofOfWork.py +113 -113
- edsl/study/SnapShot.py +80 -80
- edsl/study/Study.py +521 -528
- edsl/study/__init__.py +4 -4
- edsl/surveys/ConstructDAG.py +92 -0
- edsl/surveys/DAG.py +148 -148
- edsl/surveys/EditSurvey.py +221 -0
- edsl/surveys/InstructionHandler.py +100 -0
- edsl/surveys/Memory.py +31 -31
- edsl/surveys/MemoryManagement.py +72 -0
- edsl/surveys/MemoryPlan.py +244 -244
- edsl/surveys/Rule.py +327 -326
- edsl/surveys/RuleCollection.py +385 -387
- edsl/surveys/RuleManager.py +172 -0
- edsl/surveys/Simulator.py +75 -0
- edsl/surveys/Survey.py +1280 -1801
- edsl/surveys/SurveyCSS.py +273 -261
- edsl/surveys/SurveyExportMixin.py +259 -259
- edsl/surveys/{SurveyFlowVisualizationMixin.py → SurveyFlowVisualization.py} +181 -179
- edsl/surveys/SurveyQualtricsImport.py +284 -284
- edsl/surveys/SurveyToApp.py +141 -0
- edsl/surveys/__init__.py +5 -3
- edsl/surveys/base.py +53 -53
- edsl/surveys/descriptors.py +60 -56
- edsl/surveys/instructions/ChangeInstruction.py +48 -49
- edsl/surveys/instructions/Instruction.py +56 -65
- edsl/surveys/instructions/InstructionCollection.py +82 -77
- edsl/templates/error_reporting/base.html +23 -23
- edsl/templates/error_reporting/exceptions_by_model.html +34 -34
- edsl/templates/error_reporting/exceptions_by_question_name.html +16 -16
- edsl/templates/error_reporting/exceptions_by_type.html +16 -16
- edsl/templates/error_reporting/interview_details.html +115 -115
- edsl/templates/error_reporting/interviews.html +19 -19
- edsl/templates/error_reporting/overview.html +4 -4
- edsl/templates/error_reporting/performance_plot.html +1 -1
- edsl/templates/error_reporting/report.css +73 -73
- edsl/templates/error_reporting/report.html +117 -117
- edsl/templates/error_reporting/report.js +25 -25
- edsl/test_h +1 -0
- edsl/tools/__init__.py +1 -1
- edsl/tools/clusters.py +192 -192
- edsl/tools/embeddings.py +27 -27
- edsl/tools/embeddings_plotting.py +118 -118
- edsl/tools/plotting.py +112 -112
- edsl/tools/summarize.py +18 -18
- edsl/utilities/PrettyList.py +56 -0
- edsl/utilities/SystemInfo.py +28 -28
- edsl/utilities/__init__.py +22 -22
- edsl/utilities/ast_utilities.py +25 -25
- edsl/utilities/data/Registry.py +6 -6
- edsl/utilities/data/__init__.py +1 -1
- edsl/utilities/data/scooter_results.json +1 -1
- edsl/utilities/decorators.py +77 -77
- edsl/utilities/gcp_bucket/cloud_storage.py +96 -96
- edsl/utilities/gcp_bucket/example.py +50 -0
- edsl/utilities/interface.py +627 -627
- edsl/utilities/is_notebook.py +18 -0
- edsl/utilities/is_valid_variable_name.py +11 -0
- edsl/utilities/naming_utilities.py +263 -263
- edsl/utilities/remove_edsl_version.py +24 -0
- edsl/utilities/repair_functions.py +28 -28
- edsl/utilities/restricted_python.py +70 -70
- edsl/utilities/utilities.py +436 -424
- {edsl-0.1.39.dev3.dist-info → edsl-0.1.39.dev4.dist-info}/LICENSE +21 -21
- {edsl-0.1.39.dev3.dist-info → edsl-0.1.39.dev4.dist-info}/METADATA +13 -11
- edsl-0.1.39.dev4.dist-info/RECORD +361 -0
- edsl/language_models/KeyLookup.py +0 -30
- edsl/language_models/registry.py +0 -190
- edsl/language_models/unused/ReplicateBase.py +0 -83
- edsl/results/ResultsDBMixin.py +0 -238
- edsl-0.1.39.dev3.dist-info/RECORD +0 -277
- {edsl-0.1.39.dev3.dist-info → edsl-0.1.39.dev4.dist-info}/WHEEL +0 -0
edsl/utilities/decorators.py
CHANGED
@@ -1,77 +1,77 @@
|
|
1
|
-
import functools
|
2
|
-
import asyncio
|
3
|
-
import nest_asyncio
|
4
|
-
|
5
|
-
nest_asyncio.apply()
|
6
|
-
|
7
|
-
from edsl import __version__ as edsl_version
|
8
|
-
|
9
|
-
|
10
|
-
def add_edsl_version(func):
|
11
|
-
"""
|
12
|
-
Decorator for EDSL objects' `to_dict` method.
|
13
|
-
- Adds the EDSL version and class name to the dictionary.
|
14
|
-
"""
|
15
|
-
|
16
|
-
@functools.wraps(func)
|
17
|
-
def wrapper(*args, **kwargs):
|
18
|
-
d = func(*args, **kwargs)
|
19
|
-
d["edsl_version"] = edsl_version
|
20
|
-
d["edsl_class_name"] = func.__qualname__.split(".")[0]
|
21
|
-
return d
|
22
|
-
|
23
|
-
return wrapper
|
24
|
-
|
25
|
-
|
26
|
-
def remove_edsl_version(func):
|
27
|
-
"""
|
28
|
-
Decorator for the EDSL objects' `from_dict` method.
|
29
|
-
- Removes the EDSL version and class name from the dictionary.
|
30
|
-
- Ensures backwards compatibility with older versions of EDSL.
|
31
|
-
"""
|
32
|
-
|
33
|
-
@functools.wraps(func)
|
34
|
-
def wrapper(cls, data, *args, **kwargs):
|
35
|
-
data_copy = dict(data)
|
36
|
-
edsl_version = data_copy.pop("edsl_version", None)
|
37
|
-
edsl_classname = data_copy.pop("edsl_class_name", None)
|
38
|
-
|
39
|
-
# Version- and class-specific logic here
|
40
|
-
if edsl_classname == "Survey":
|
41
|
-
if edsl_version is None or edsl_version <= "0.1.20":
|
42
|
-
data_copy["question_groups"] = {}
|
43
|
-
|
44
|
-
return func(cls, data_copy, *args, **kwargs)
|
45
|
-
|
46
|
-
return wrapper
|
47
|
-
|
48
|
-
|
49
|
-
def jupyter_nb_handler(func):
|
50
|
-
"""Decorator to run an async function in the event loop if it's running, or synchronously otherwise."""
|
51
|
-
|
52
|
-
@functools.wraps(func)
|
53
|
-
async def async_wrapper(*args, **kwargs):
|
54
|
-
# This is an async wrapper to await the coroutine
|
55
|
-
return await func(*args, **kwargs)
|
56
|
-
|
57
|
-
def wrapper(*args, **kwargs):
|
58
|
-
loop = asyncio.get_event_loop()
|
59
|
-
if loop.is_running():
|
60
|
-
# If the loop is running, schedule the coroutine and wait for the result
|
61
|
-
future = asyncio.ensure_future(async_wrapper(*args, **kwargs))
|
62
|
-
return loop.run_until_complete(future)
|
63
|
-
else:
|
64
|
-
# If the loop is not running, run the coroutine to completion
|
65
|
-
return asyncio.run(async_wrapper(*args, **kwargs))
|
66
|
-
|
67
|
-
return wrapper
|
68
|
-
|
69
|
-
|
70
|
-
def sync_wrapper(async_func):
|
71
|
-
"""Decorator to create a synchronous wrapper for an asynchronous function."""
|
72
|
-
|
73
|
-
@functools.wraps(async_func)
|
74
|
-
def wrapper(*args, **kwargs):
|
75
|
-
return asyncio.run(async_func(*args, **kwargs))
|
76
|
-
|
77
|
-
return wrapper
|
1
|
+
import functools
|
2
|
+
import asyncio
|
3
|
+
import nest_asyncio
|
4
|
+
|
5
|
+
nest_asyncio.apply()
|
6
|
+
|
7
|
+
from edsl import __version__ as edsl_version
|
8
|
+
|
9
|
+
|
10
|
+
def add_edsl_version(func):
|
11
|
+
"""
|
12
|
+
Decorator for EDSL objects' `to_dict` method.
|
13
|
+
- Adds the EDSL version and class name to the dictionary.
|
14
|
+
"""
|
15
|
+
|
16
|
+
@functools.wraps(func)
|
17
|
+
def wrapper(*args, **kwargs):
|
18
|
+
d = func(*args, **kwargs)
|
19
|
+
d["edsl_version"] = edsl_version
|
20
|
+
d["edsl_class_name"] = func.__qualname__.split(".")[0]
|
21
|
+
return d
|
22
|
+
|
23
|
+
return wrapper
|
24
|
+
|
25
|
+
|
26
|
+
def remove_edsl_version(func):
|
27
|
+
"""
|
28
|
+
Decorator for the EDSL objects' `from_dict` method.
|
29
|
+
- Removes the EDSL version and class name from the dictionary.
|
30
|
+
- Ensures backwards compatibility with older versions of EDSL.
|
31
|
+
"""
|
32
|
+
|
33
|
+
@functools.wraps(func)
|
34
|
+
def wrapper(cls, data, *args, **kwargs):
|
35
|
+
data_copy = dict(data)
|
36
|
+
edsl_version = data_copy.pop("edsl_version", None)
|
37
|
+
edsl_classname = data_copy.pop("edsl_class_name", None)
|
38
|
+
|
39
|
+
# Version- and class-specific logic here
|
40
|
+
if edsl_classname == "Survey":
|
41
|
+
if edsl_version is None or edsl_version <= "0.1.20":
|
42
|
+
data_copy["question_groups"] = {}
|
43
|
+
|
44
|
+
return func(cls, data_copy, *args, **kwargs)
|
45
|
+
|
46
|
+
return wrapper
|
47
|
+
|
48
|
+
|
49
|
+
def jupyter_nb_handler(func):
|
50
|
+
"""Decorator to run an async function in the event loop if it's running, or synchronously otherwise."""
|
51
|
+
|
52
|
+
@functools.wraps(func)
|
53
|
+
async def async_wrapper(*args, **kwargs):
|
54
|
+
# This is an async wrapper to await the coroutine
|
55
|
+
return await func(*args, **kwargs)
|
56
|
+
|
57
|
+
def wrapper(*args, **kwargs):
|
58
|
+
loop = asyncio.get_event_loop()
|
59
|
+
if loop.is_running():
|
60
|
+
# If the loop is running, schedule the coroutine and wait for the result
|
61
|
+
future = asyncio.ensure_future(async_wrapper(*args, **kwargs))
|
62
|
+
return loop.run_until_complete(future)
|
63
|
+
else:
|
64
|
+
# If the loop is not running, run the coroutine to completion
|
65
|
+
return asyncio.run(async_wrapper(*args, **kwargs))
|
66
|
+
|
67
|
+
return wrapper
|
68
|
+
|
69
|
+
|
70
|
+
def sync_wrapper(async_func):
|
71
|
+
"""Decorator to create a synchronous wrapper for an asynchronous function."""
|
72
|
+
|
73
|
+
@functools.wraps(async_func)
|
74
|
+
def wrapper(*args, **kwargs):
|
75
|
+
return asyncio.run(async_func(*args, **kwargs))
|
76
|
+
|
77
|
+
return wrapper
|
@@ -1,96 +1,96 @@
|
|
1
|
-
import requests
|
2
|
-
|
3
|
-
|
4
|
-
class CloudStorageManager:
|
5
|
-
def __init__(self, secret_token=None):
|
6
|
-
self.api_url = "https://bucket-server-tte53lsfxq-uc.a.run.app"
|
7
|
-
self.secret_token = secret_token
|
8
|
-
|
9
|
-
def get_signed_url(self, file_name, operation="upload"):
|
10
|
-
"""Get a signed URL for uploading or downloading a file."""
|
11
|
-
|
12
|
-
if operation == "upload":
|
13
|
-
if self.secret_token == None:
|
14
|
-
raise "Set secret_token for upload permissions"
|
15
|
-
headers = {
|
16
|
-
"Authorization": self.secret_token,
|
17
|
-
"Content-Type": "application/json",
|
18
|
-
}
|
19
|
-
else:
|
20
|
-
headers = {
|
21
|
-
"Content-Type": "application/json",
|
22
|
-
}
|
23
|
-
data = {"file_name": file_name}
|
24
|
-
endpoint = f"{self.api_url}/generate-{operation}-signed-url"
|
25
|
-
response = requests.post(endpoint, json=data, headers=headers)
|
26
|
-
|
27
|
-
if response.status_code == 200:
|
28
|
-
return response.json().get("signed_url")
|
29
|
-
else:
|
30
|
-
raise Exception(
|
31
|
-
f"Failed to get signed URL: {response.status_code} {response.text}"
|
32
|
-
)
|
33
|
-
|
34
|
-
def upload_file(self, file_path, upload_file_name):
|
35
|
-
"""Upload a file to the signed URL."""
|
36
|
-
signed_url = self.get_signed_url(upload_file_name, operation="upload")
|
37
|
-
|
38
|
-
with open(file_path, "rb") as file:
|
39
|
-
upload_response = requests.put(
|
40
|
-
signed_url,
|
41
|
-
data=file,
|
42
|
-
headers={"Content-Type": "application/octet-stream"},
|
43
|
-
)
|
44
|
-
|
45
|
-
if upload_response.status_code == 200:
|
46
|
-
print("File uploaded successfully")
|
47
|
-
else:
|
48
|
-
raise Exception(
|
49
|
-
f"Failed to upload file: {upload_response.status_code} {upload_response.text}"
|
50
|
-
)
|
51
|
-
|
52
|
-
def download_file(self, file_name, save_name):
|
53
|
-
"""Download a file from the signed URL."""
|
54
|
-
|
55
|
-
signed_url = self.get_signed_url(file_name, operation="download")
|
56
|
-
download_response = requests.get(signed_url, stream=True)
|
57
|
-
|
58
|
-
if download_response.status_code == 200:
|
59
|
-
with open(save_name, "wb") as file:
|
60
|
-
for chunk in download_response.iter_content(chunk_size=8192):
|
61
|
-
file.write(chunk)
|
62
|
-
print("File downloaded successfully")
|
63
|
-
else:
|
64
|
-
raise Exception(
|
65
|
-
f"Failed to download file: {download_response.status_code} {download_response.text}"
|
66
|
-
)
|
67
|
-
|
68
|
-
def delete_file(self, file_name):
|
69
|
-
"""Delete a file from the cloud storage."""
|
70
|
-
headers = {
|
71
|
-
"Authorization": self.secret_token,
|
72
|
-
"Content-Type": "application/json",
|
73
|
-
}
|
74
|
-
data = {"file_name": file_name}
|
75
|
-
endpoint = f"{self.api_url}/delete-file"
|
76
|
-
response = requests.delete(endpoint, params=data, headers=headers)
|
77
|
-
|
78
|
-
if response.status_code == 200:
|
79
|
-
print("File deleted successfully")
|
80
|
-
else:
|
81
|
-
raise Exception(
|
82
|
-
f"Failed to delete file: {response.status_code} {response.text}"
|
83
|
-
)
|
84
|
-
|
85
|
-
def list_files(self):
|
86
|
-
url = self.api_url + "/list_files"
|
87
|
-
headers = {
|
88
|
-
"Authorization": self.secret_token,
|
89
|
-
"Content-Type": "application/json",
|
90
|
-
}
|
91
|
-
res = requests.get(url, headers=headers)
|
92
|
-
data = res.json()
|
93
|
-
for x in data["data"]:
|
94
|
-
x["url"] = self.api_url + "/file/" + x["shaKey"]
|
95
|
-
|
96
|
-
return data
|
1
|
+
import requests
|
2
|
+
|
3
|
+
|
4
|
+
class CloudStorageManager:
|
5
|
+
def __init__(self, secret_token=None):
|
6
|
+
self.api_url = "https://bucket-server-tte53lsfxq-uc.a.run.app"
|
7
|
+
self.secret_token = secret_token
|
8
|
+
|
9
|
+
def get_signed_url(self, file_name, operation="upload"):
|
10
|
+
"""Get a signed URL for uploading or downloading a file."""
|
11
|
+
|
12
|
+
if operation == "upload":
|
13
|
+
if self.secret_token == None:
|
14
|
+
raise "Set secret_token for upload permissions"
|
15
|
+
headers = {
|
16
|
+
"Authorization": self.secret_token,
|
17
|
+
"Content-Type": "application/json",
|
18
|
+
}
|
19
|
+
else:
|
20
|
+
headers = {
|
21
|
+
"Content-Type": "application/json",
|
22
|
+
}
|
23
|
+
data = {"file_name": file_name}
|
24
|
+
endpoint = f"{self.api_url}/generate-{operation}-signed-url"
|
25
|
+
response = requests.post(endpoint, json=data, headers=headers)
|
26
|
+
|
27
|
+
if response.status_code == 200:
|
28
|
+
return response.json().get("signed_url")
|
29
|
+
else:
|
30
|
+
raise Exception(
|
31
|
+
f"Failed to get signed URL: {response.status_code} {response.text}"
|
32
|
+
)
|
33
|
+
|
34
|
+
def upload_file(self, file_path, upload_file_name):
|
35
|
+
"""Upload a file to the signed URL."""
|
36
|
+
signed_url = self.get_signed_url(upload_file_name, operation="upload")
|
37
|
+
|
38
|
+
with open(file_path, "rb") as file:
|
39
|
+
upload_response = requests.put(
|
40
|
+
signed_url,
|
41
|
+
data=file,
|
42
|
+
headers={"Content-Type": "application/octet-stream"},
|
43
|
+
)
|
44
|
+
|
45
|
+
if upload_response.status_code == 200:
|
46
|
+
print("File uploaded successfully")
|
47
|
+
else:
|
48
|
+
raise Exception(
|
49
|
+
f"Failed to upload file: {upload_response.status_code} {upload_response.text}"
|
50
|
+
)
|
51
|
+
|
52
|
+
def download_file(self, file_name, save_name):
|
53
|
+
"""Download a file from the signed URL."""
|
54
|
+
|
55
|
+
signed_url = self.get_signed_url(file_name, operation="download")
|
56
|
+
download_response = requests.get(signed_url, stream=True)
|
57
|
+
|
58
|
+
if download_response.status_code == 200:
|
59
|
+
with open(save_name, "wb") as file:
|
60
|
+
for chunk in download_response.iter_content(chunk_size=8192):
|
61
|
+
file.write(chunk)
|
62
|
+
print("File downloaded successfully")
|
63
|
+
else:
|
64
|
+
raise Exception(
|
65
|
+
f"Failed to download file: {download_response.status_code} {download_response.text}"
|
66
|
+
)
|
67
|
+
|
68
|
+
def delete_file(self, file_name):
|
69
|
+
"""Delete a file from the cloud storage."""
|
70
|
+
headers = {
|
71
|
+
"Authorization": self.secret_token,
|
72
|
+
"Content-Type": "application/json",
|
73
|
+
}
|
74
|
+
data = {"file_name": file_name}
|
75
|
+
endpoint = f"{self.api_url}/delete-file"
|
76
|
+
response = requests.delete(endpoint, params=data, headers=headers)
|
77
|
+
|
78
|
+
if response.status_code == 200:
|
79
|
+
print("File deleted successfully")
|
80
|
+
else:
|
81
|
+
raise Exception(
|
82
|
+
f"Failed to delete file: {response.status_code} {response.text}"
|
83
|
+
)
|
84
|
+
|
85
|
+
def list_files(self):
|
86
|
+
url = self.api_url + "/list_files"
|
87
|
+
headers = {
|
88
|
+
"Authorization": self.secret_token,
|
89
|
+
"Content-Type": "application/json",
|
90
|
+
}
|
91
|
+
res = requests.get(url, headers=headers)
|
92
|
+
data = res.json()
|
93
|
+
for x in data["data"]:
|
94
|
+
x["url"] = self.api_url + "/file/" + x["shaKey"]
|
95
|
+
|
96
|
+
return data
|
@@ -0,0 +1,50 @@
|
|
1
|
+
from edsl.utilities.gcp_bucket.cloud_storage import CloudStorageManager
|
2
|
+
|
3
|
+
# API URLs
|
4
|
+
secret_token = "your-secret-token"
|
5
|
+
|
6
|
+
# File paths and names
|
7
|
+
upload_file_path = "./app.py"
|
8
|
+
upload_file_name = "new_upload.py"
|
9
|
+
|
10
|
+
# Initialize CloudStorageManager
|
11
|
+
manager = CloudStorageManager(secret_token=secret_token) # secret_token only for upload operations
|
12
|
+
|
13
|
+
# Upload Process
|
14
|
+
try:
|
15
|
+
manager.upload_file(upload_file_path, upload_file_name)
|
16
|
+
print("File upload process completed.")
|
17
|
+
except Exception as e:
|
18
|
+
print(f"Upload error: {str(e)}")
|
19
|
+
|
20
|
+
# Download Process
|
21
|
+
file_name = "new_upload.py" # Name for the downloaded file
|
22
|
+
save_name = "res_download.py"
|
23
|
+
try:
|
24
|
+
manager.download_file(file_name, save_name)
|
25
|
+
print("File download process completed.")
|
26
|
+
except Exception as e:
|
27
|
+
print(f"Download error: {str(e)}")
|
28
|
+
|
29
|
+
# List files
|
30
|
+
try:
|
31
|
+
print("listing files")
|
32
|
+
out = manager.list_files()
|
33
|
+
for x in out["data"]:
|
34
|
+
print(f"file_name: {x['file_name']}", f"url: {x['url']}")
|
35
|
+
except Exception as e:
|
36
|
+
print(f"Exception in listing files", str(e))
|
37
|
+
|
38
|
+
# Delete file
|
39
|
+
try:
|
40
|
+
manager.delete_file("new_upload.py")
|
41
|
+
except Exception as e:
|
42
|
+
print(f"Exception in deleting file", str(e))
|
43
|
+
# List files
|
44
|
+
try:
|
45
|
+
print("listing files")
|
46
|
+
out = manager.list_files()
|
47
|
+
for x in out["data"]:
|
48
|
+
print(f"file_name: {x['file_name']}", f"url: {x['url']}")
|
49
|
+
except Exception as e:
|
50
|
+
print(f"Exception in listing files", str(e))
|