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/notebooks/Notebook.py
CHANGED
@@ -1,258 +1,263 @@
|
|
1
|
-
"""A Notebook is a utility class that allows you to easily share/pull ipynbs from Coop."""
|
2
|
-
|
3
|
-
from __future__ import annotations
|
4
|
-
import json
|
5
|
-
from typing import Dict, List, Optional, Union
|
6
|
-
from uuid import uuid4
|
7
|
-
from edsl.Base import Base
|
8
|
-
from edsl.utilities.decorators import add_edsl_version, remove_edsl_version
|
9
|
-
|
10
|
-
|
11
|
-
class Notebook(Base):
|
12
|
-
"""
|
13
|
-
A Notebook is a utility class that allows you to easily share/pull ipynbs from Coop.
|
14
|
-
"""
|
15
|
-
|
16
|
-
default_name = "notebook"
|
17
|
-
|
18
|
-
def __init__(
|
19
|
-
self,
|
20
|
-
|
21
|
-
|
22
|
-
name: Optional[str] = None,
|
23
|
-
):
|
24
|
-
"""
|
25
|
-
Initialize a new Notebook.
|
26
|
-
|
27
|
-
:param data: A dictionary representing the notebook data.
|
28
|
-
This dictionary must conform to the official Jupyter Notebook format, as defined by nbformat.
|
29
|
-
:param path: A filepath from which to load the notebook.
|
30
|
-
If no path is provided, assume this code is run in a notebook and try to load the current notebook from file.
|
31
|
-
:param name: A name for the Notebook.
|
32
|
-
"""
|
33
|
-
import nbformat
|
34
|
-
|
35
|
-
# Load current notebook path as fallback (VS Code only)
|
36
|
-
|
37
|
-
if
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
self.data =
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
#
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
nb.
|
71
|
-
|
72
|
-
#
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
"""
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
"""
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
""
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
""
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
"
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
""
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
{
|
218
|
-
"cell_type": "
|
219
|
-
"
|
220
|
-
"
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
"""
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
1
|
+
"""A Notebook is a utility class that allows you to easily share/pull ipynbs from Coop."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
import json
|
5
|
+
from typing import Dict, List, Optional, Union
|
6
|
+
from uuid import uuid4
|
7
|
+
from edsl.Base import Base
|
8
|
+
from edsl.utilities.decorators import add_edsl_version, remove_edsl_version
|
9
|
+
|
10
|
+
|
11
|
+
class Notebook(Base):
|
12
|
+
"""
|
13
|
+
A Notebook is a utility class that allows you to easily share/pull ipynbs from Coop.
|
14
|
+
"""
|
15
|
+
|
16
|
+
default_name = "notebook"
|
17
|
+
|
18
|
+
def __init__(
|
19
|
+
self,
|
20
|
+
path: Optional[str] = None,
|
21
|
+
data: Optional[Dict] = None,
|
22
|
+
name: Optional[str] = None,
|
23
|
+
):
|
24
|
+
"""
|
25
|
+
Initialize a new Notebook.
|
26
|
+
|
27
|
+
:param data: A dictionary representing the notebook data.
|
28
|
+
This dictionary must conform to the official Jupyter Notebook format, as defined by nbformat.
|
29
|
+
:param path: A filepath from which to load the notebook.
|
30
|
+
If no path is provided, assume this code is run in a notebook and try to load the current notebook from file.
|
31
|
+
:param name: A name for the Notebook.
|
32
|
+
"""
|
33
|
+
import nbformat
|
34
|
+
|
35
|
+
# Load current notebook path as fallback (VS Code only)
|
36
|
+
current_notebook_path = globals().get("__vsc_ipynb_file__")
|
37
|
+
if path is not None:
|
38
|
+
with open(path, mode="r", encoding="utf-8") as f:
|
39
|
+
data = nbformat.read(f, as_version=4)
|
40
|
+
self.data = json.loads(json.dumps(data))
|
41
|
+
elif data is not None:
|
42
|
+
nbformat.validate(data)
|
43
|
+
self.data = data
|
44
|
+
elif current_notebook_path is not None:
|
45
|
+
with open(current_notebook_path, mode="r", encoding="utf-8") as f:
|
46
|
+
data = nbformat.read(f, as_version=4)
|
47
|
+
self.data = json.loads(json.dumps(data))
|
48
|
+
else:
|
49
|
+
# TODO: Support for IDEs other than VSCode
|
50
|
+
raise NotImplementedError(
|
51
|
+
"Cannot create a notebook from within itself in this development environment"
|
52
|
+
)
|
53
|
+
|
54
|
+
# TODO: perhaps add sanity check function
|
55
|
+
# 1. could check if the notebook is a valid notebook
|
56
|
+
# 2. could check notebook uses EDSL
|
57
|
+
# ....
|
58
|
+
|
59
|
+
self.name = name or self.default_name
|
60
|
+
|
61
|
+
@classmethod
|
62
|
+
def from_script(cls, path: str, name: Optional[str] = None) -> "Notebook":
|
63
|
+
import nbformat
|
64
|
+
|
65
|
+
# Read the script file
|
66
|
+
with open(path, "r") as script_file:
|
67
|
+
script_content = script_file.read()
|
68
|
+
|
69
|
+
# Create a new Jupyter notebook
|
70
|
+
nb = nbformat.v4.new_notebook()
|
71
|
+
|
72
|
+
# Add the script content to the first cell
|
73
|
+
first_cell = nbformat.v4.new_code_cell(script_content)
|
74
|
+
nb.cells.append(first_cell)
|
75
|
+
|
76
|
+
# Create a Notebook instance with the notebook data
|
77
|
+
notebook_instance = cls(nb)
|
78
|
+
|
79
|
+
return notebook_instance
|
80
|
+
|
81
|
+
@classmethod
|
82
|
+
def from_current_script(cls) -> "Notebook":
|
83
|
+
import inspect
|
84
|
+
import os
|
85
|
+
|
86
|
+
# Get the path to the current file
|
87
|
+
current_frame = inspect.currentframe()
|
88
|
+
caller_frame = inspect.getouterframes(current_frame, 2)
|
89
|
+
current_file_path = os.path.abspath(caller_frame[1].filename)
|
90
|
+
|
91
|
+
# Use from_script to create the notebook
|
92
|
+
return cls.from_script(current_file_path)
|
93
|
+
|
94
|
+
def __eq__(self, other):
|
95
|
+
"""
|
96
|
+
Check if two Notebooks are equal.
|
97
|
+
This only checks the notebook data.
|
98
|
+
"""
|
99
|
+
return self.data == other.data
|
100
|
+
|
101
|
+
def __hash__(self) -> int:
|
102
|
+
"""
|
103
|
+
Allow the model to be used as a key in a dictionary.
|
104
|
+
"""
|
105
|
+
from edsl.utilities.utilities import dict_hash
|
106
|
+
|
107
|
+
return dict_hash(self.data["cells"])
|
108
|
+
|
109
|
+
def to_dict(self, add_edsl_version=False) -> dict:
|
110
|
+
"""
|
111
|
+
Serialize to a dictionary.
|
112
|
+
"""
|
113
|
+
d = {"name": self.name, "data": self.data}
|
114
|
+
if add_edsl_version:
|
115
|
+
from edsl import __version__
|
116
|
+
|
117
|
+
d["edsl_version"] = __version__
|
118
|
+
d["edsl_class_name"] = self.__class__.__name__
|
119
|
+
return d
|
120
|
+
|
121
|
+
@classmethod
|
122
|
+
@remove_edsl_version
|
123
|
+
def from_dict(cls, d: Dict) -> "Notebook":
|
124
|
+
"""
|
125
|
+
Convert a dictionary representation of a Notebook to a Notebook object.
|
126
|
+
"""
|
127
|
+
return cls(data=d["data"], name=d["name"])
|
128
|
+
|
129
|
+
def to_file(self, path: str):
|
130
|
+
"""
|
131
|
+
Save the notebook at the specified filepath.
|
132
|
+
"""
|
133
|
+
import nbformat
|
134
|
+
|
135
|
+
nbformat.write(nbformat.from_dict(self.data), fp=path)
|
136
|
+
|
137
|
+
def __repr__(self):
|
138
|
+
"""
|
139
|
+
Return representation of Notebook.
|
140
|
+
"""
|
141
|
+
return f'Notebook(data={self.data}, name="""{self.name}""")'
|
142
|
+
|
143
|
+
def _repr_html_(self):
|
144
|
+
"""
|
145
|
+
Return HTML representation of Notebook.
|
146
|
+
"""
|
147
|
+
from nbconvert import HTMLExporter
|
148
|
+
import nbformat
|
149
|
+
|
150
|
+
notebook = nbformat.from_dict(self.data)
|
151
|
+
html_exporter = HTMLExporter(template_name="basic")
|
152
|
+
(body, _) = html_exporter.from_notebook_node(notebook)
|
153
|
+
return body
|
154
|
+
|
155
|
+
def _table(self) -> tuple[dict, list]:
|
156
|
+
"""
|
157
|
+
Prepare generic table data.
|
158
|
+
"""
|
159
|
+
table_data = []
|
160
|
+
|
161
|
+
notebook_preview = ""
|
162
|
+
for cell in self.data["cells"]:
|
163
|
+
if "source" in cell:
|
164
|
+
notebook_preview += f"{cell['source']}\n"
|
165
|
+
if len(notebook_preview) > 1000:
|
166
|
+
notebook_preview = f"{notebook_preview[:1000]} [...]"
|
167
|
+
break
|
168
|
+
notebook_preview = notebook_preview.rstrip()
|
169
|
+
|
170
|
+
table_data.append(
|
171
|
+
{
|
172
|
+
"Attribute": "name",
|
173
|
+
"Value": repr(self.name),
|
174
|
+
}
|
175
|
+
)
|
176
|
+
table_data.append(
|
177
|
+
{
|
178
|
+
"Attribute": "notebook_preview",
|
179
|
+
"Value": notebook_preview,
|
180
|
+
}
|
181
|
+
)
|
182
|
+
|
183
|
+
column_names = ["Attribute", "Value"]
|
184
|
+
return table_data, column_names
|
185
|
+
|
186
|
+
def rich_print(self) -> "Table":
|
187
|
+
"""
|
188
|
+
Display a Notebook as a rich table.
|
189
|
+
"""
|
190
|
+
from rich.table import Table
|
191
|
+
|
192
|
+
table_data, column_names = self._table()
|
193
|
+
table = Table(title=f"{self.__class__.__name__} Attributes")
|
194
|
+
for column in column_names:
|
195
|
+
table.add_column(column, style="bold")
|
196
|
+
|
197
|
+
for row in table_data:
|
198
|
+
row_data = [row[column] for column in column_names]
|
199
|
+
table.add_row(*row_data)
|
200
|
+
|
201
|
+
return table
|
202
|
+
|
203
|
+
@classmethod
|
204
|
+
def example(cls, randomize: bool = False) -> Notebook:
|
205
|
+
"""
|
206
|
+
Returns an example Notebook instance.
|
207
|
+
|
208
|
+
:param randomize: If True, adds a random string one of the cells' output.
|
209
|
+
"""
|
210
|
+
addition = "" if not randomize else str(uuid4())
|
211
|
+
cells = [
|
212
|
+
{
|
213
|
+
"cell_type": "markdown",
|
214
|
+
"metadata": dict(),
|
215
|
+
"source": "# Test notebook",
|
216
|
+
},
|
217
|
+
{
|
218
|
+
"cell_type": "code",
|
219
|
+
"execution_count": 1,
|
220
|
+
"metadata": dict(),
|
221
|
+
"outputs": [
|
222
|
+
{
|
223
|
+
"name": "stdout",
|
224
|
+
"output_type": "stream",
|
225
|
+
"text": f"Hello world!\n{addition}",
|
226
|
+
}
|
227
|
+
],
|
228
|
+
"source": 'print("Hello world!")',
|
229
|
+
},
|
230
|
+
]
|
231
|
+
data = {
|
232
|
+
"metadata": dict(),
|
233
|
+
"nbformat": 4,
|
234
|
+
"nbformat_minor": 4,
|
235
|
+
"cells": cells,
|
236
|
+
}
|
237
|
+
return cls(data=data)
|
238
|
+
|
239
|
+
def code(self) -> List[str]:
|
240
|
+
"""
|
241
|
+
Return the code that could be used to create this Notebook.
|
242
|
+
"""
|
243
|
+
lines = []
|
244
|
+
lines.append("from edsl import Notebook")
|
245
|
+
lines.append(f'nb = Notebook(data={self.data}, name="""{self.name}""")')
|
246
|
+
return lines
|
247
|
+
|
248
|
+
def to_latex(self, filename: str):
|
249
|
+
"""
|
250
|
+
Convert notebook to LaTeX and create a folder with all necessary components.
|
251
|
+
|
252
|
+
:param filename: Name of the output folder and main tex file (without extension)
|
253
|
+
"""
|
254
|
+
from edsl.notebooks.NotebookToLaTeX import NotebookToLaTeX
|
255
|
+
|
256
|
+
NotebookToLaTeX(self).convert(filename)
|
257
|
+
|
258
|
+
|
259
|
+
if __name__ == "__main__":
|
260
|
+
from edsl import Notebook
|
261
|
+
|
262
|
+
notebook = Notebook.example()
|
263
|
+
assert notebook == notebook.from_dict(notebook.to_dict())
|