edsl 0.1.38.dev4__py3-none-any.whl → 0.1.39__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.
Files changed (212) hide show
  1. edsl/Base.py +197 -116
  2. edsl/__init__.py +15 -7
  3. edsl/__version__.py +1 -1
  4. edsl/agents/Agent.py +351 -147
  5. edsl/agents/AgentList.py +211 -73
  6. edsl/agents/Invigilator.py +101 -50
  7. edsl/agents/InvigilatorBase.py +62 -70
  8. edsl/agents/PromptConstructor.py +143 -225
  9. edsl/agents/QuestionInstructionPromptBuilder.py +128 -0
  10. edsl/agents/QuestionTemplateReplacementsBuilder.py +137 -0
  11. edsl/agents/__init__.py +0 -1
  12. edsl/agents/prompt_helpers.py +3 -3
  13. edsl/agents/question_option_processor.py +172 -0
  14. edsl/auto/AutoStudy.py +18 -5
  15. edsl/auto/StageBase.py +53 -40
  16. edsl/auto/StageQuestions.py +2 -1
  17. edsl/auto/utilities.py +0 -6
  18. edsl/config.py +22 -2
  19. edsl/conversation/car_buying.py +2 -1
  20. edsl/coop/CoopFunctionsMixin.py +15 -0
  21. edsl/coop/ExpectedParrotKeyHandler.py +125 -0
  22. edsl/coop/PriceFetcher.py +1 -1
  23. edsl/coop/coop.py +125 -47
  24. edsl/coop/utils.py +14 -14
  25. edsl/data/Cache.py +45 -27
  26. edsl/data/CacheEntry.py +12 -15
  27. edsl/data/CacheHandler.py +31 -12
  28. edsl/data/RemoteCacheSync.py +154 -46
  29. edsl/data/__init__.py +4 -3
  30. edsl/data_transfer_models.py +2 -1
  31. edsl/enums.py +27 -0
  32. edsl/exceptions/__init__.py +50 -50
  33. edsl/exceptions/agents.py +12 -0
  34. edsl/exceptions/inference_services.py +5 -0
  35. edsl/exceptions/questions.py +24 -6
  36. edsl/exceptions/scenarios.py +7 -0
  37. edsl/inference_services/AnthropicService.py +38 -19
  38. edsl/inference_services/AvailableModelCacheHandler.py +184 -0
  39. edsl/inference_services/AvailableModelFetcher.py +215 -0
  40. edsl/inference_services/AwsBedrock.py +0 -2
  41. edsl/inference_services/AzureAI.py +0 -2
  42. edsl/inference_services/GoogleService.py +7 -12
  43. edsl/inference_services/InferenceServiceABC.py +18 -85
  44. edsl/inference_services/InferenceServicesCollection.py +120 -79
  45. edsl/inference_services/MistralAIService.py +0 -3
  46. edsl/inference_services/OpenAIService.py +47 -35
  47. edsl/inference_services/PerplexityService.py +0 -3
  48. edsl/inference_services/ServiceAvailability.py +135 -0
  49. edsl/inference_services/TestService.py +11 -10
  50. edsl/inference_services/TogetherAIService.py +5 -3
  51. edsl/inference_services/data_structures.py +134 -0
  52. edsl/jobs/AnswerQuestionFunctionConstructor.py +223 -0
  53. edsl/jobs/Answers.py +1 -14
  54. edsl/jobs/FetchInvigilator.py +47 -0
  55. edsl/jobs/InterviewTaskManager.py +98 -0
  56. edsl/jobs/InterviewsConstructor.py +50 -0
  57. edsl/jobs/Jobs.py +356 -431
  58. edsl/jobs/JobsChecks.py +35 -10
  59. edsl/jobs/JobsComponentConstructor.py +189 -0
  60. edsl/jobs/JobsPrompts.py +6 -4
  61. edsl/jobs/JobsRemoteInferenceHandler.py +205 -133
  62. edsl/jobs/JobsRemoteInferenceLogger.py +239 -0
  63. edsl/jobs/RequestTokenEstimator.py +30 -0
  64. edsl/jobs/async_interview_runner.py +138 -0
  65. edsl/jobs/buckets/BucketCollection.py +44 -3
  66. edsl/jobs/buckets/TokenBucket.py +53 -21
  67. edsl/jobs/buckets/TokenBucketAPI.py +211 -0
  68. edsl/jobs/buckets/TokenBucketClient.py +191 -0
  69. edsl/jobs/check_survey_scenario_compatibility.py +85 -0
  70. edsl/jobs/data_structures.py +120 -0
  71. edsl/jobs/decorators.py +35 -0
  72. edsl/jobs/interviews/Interview.py +143 -408
  73. edsl/jobs/jobs_status_enums.py +9 -0
  74. edsl/jobs/loggers/HTMLTableJobLogger.py +304 -0
  75. edsl/jobs/results_exceptions_handler.py +98 -0
  76. edsl/jobs/runners/JobsRunnerAsyncio.py +88 -403
  77. edsl/jobs/runners/JobsRunnerStatus.py +133 -165
  78. edsl/jobs/tasks/QuestionTaskCreator.py +21 -19
  79. edsl/jobs/tasks/TaskHistory.py +38 -18
  80. edsl/jobs/tasks/task_status_enum.py +0 -2
  81. edsl/language_models/ComputeCost.py +63 -0
  82. edsl/language_models/LanguageModel.py +194 -236
  83. edsl/language_models/ModelList.py +28 -19
  84. edsl/language_models/PriceManager.py +127 -0
  85. edsl/language_models/RawResponseHandler.py +106 -0
  86. edsl/language_models/ServiceDataSources.py +0 -0
  87. edsl/language_models/__init__.py +1 -2
  88. edsl/language_models/key_management/KeyLookup.py +63 -0
  89. edsl/language_models/key_management/KeyLookupBuilder.py +273 -0
  90. edsl/language_models/key_management/KeyLookupCollection.py +38 -0
  91. edsl/language_models/key_management/__init__.py +0 -0
  92. edsl/language_models/key_management/models.py +131 -0
  93. edsl/language_models/model.py +256 -0
  94. edsl/language_models/repair.py +2 -2
  95. edsl/language_models/utilities.py +5 -4
  96. edsl/notebooks/Notebook.py +19 -14
  97. edsl/notebooks/NotebookToLaTeX.py +142 -0
  98. edsl/prompts/Prompt.py +29 -39
  99. edsl/questions/ExceptionExplainer.py +77 -0
  100. edsl/questions/HTMLQuestion.py +103 -0
  101. edsl/questions/QuestionBase.py +68 -214
  102. edsl/questions/QuestionBasePromptsMixin.py +7 -3
  103. edsl/questions/QuestionBudget.py +1 -1
  104. edsl/questions/QuestionCheckBox.py +3 -3
  105. edsl/questions/QuestionExtract.py +5 -7
  106. edsl/questions/QuestionFreeText.py +2 -3
  107. edsl/questions/QuestionList.py +10 -18
  108. edsl/questions/QuestionMatrix.py +265 -0
  109. edsl/questions/QuestionMultipleChoice.py +67 -23
  110. edsl/questions/QuestionNumerical.py +2 -4
  111. edsl/questions/QuestionRank.py +7 -17
  112. edsl/questions/SimpleAskMixin.py +4 -3
  113. edsl/questions/__init__.py +2 -1
  114. edsl/questions/{AnswerValidatorMixin.py → answer_validator_mixin.py} +47 -2
  115. edsl/questions/data_structures.py +20 -0
  116. edsl/questions/derived/QuestionLinearScale.py +6 -3
  117. edsl/questions/derived/QuestionTopK.py +1 -1
  118. edsl/questions/descriptors.py +17 -3
  119. edsl/questions/loop_processor.py +149 -0
  120. edsl/questions/{QuestionBaseGenMixin.py → question_base_gen_mixin.py} +57 -50
  121. edsl/questions/question_registry.py +1 -1
  122. edsl/questions/{ResponseValidatorABC.py → response_validator_abc.py} +40 -26
  123. edsl/questions/response_validator_factory.py +34 -0
  124. edsl/questions/templates/matrix/__init__.py +1 -0
  125. edsl/questions/templates/matrix/answering_instructions.jinja +5 -0
  126. edsl/questions/templates/matrix/question_presentation.jinja +20 -0
  127. edsl/results/CSSParameterizer.py +1 -1
  128. edsl/results/Dataset.py +170 -7
  129. edsl/results/DatasetExportMixin.py +168 -305
  130. edsl/results/DatasetTree.py +28 -8
  131. edsl/results/MarkdownToDocx.py +122 -0
  132. edsl/results/MarkdownToPDF.py +111 -0
  133. edsl/results/Result.py +298 -206
  134. edsl/results/Results.py +149 -131
  135. edsl/results/ResultsExportMixin.py +2 -0
  136. edsl/results/TableDisplay.py +98 -171
  137. edsl/results/TextEditor.py +50 -0
  138. edsl/results/__init__.py +1 -1
  139. edsl/results/file_exports.py +252 -0
  140. edsl/results/{Selector.py → results_selector.py} +23 -13
  141. edsl/results/smart_objects.py +96 -0
  142. edsl/results/table_data_class.py +12 -0
  143. edsl/results/table_renderers.py +118 -0
  144. edsl/scenarios/ConstructDownloadLink.py +109 -0
  145. edsl/scenarios/DocumentChunker.py +102 -0
  146. edsl/scenarios/DocxScenario.py +16 -0
  147. edsl/scenarios/FileStore.py +150 -239
  148. edsl/scenarios/PdfExtractor.py +40 -0
  149. edsl/scenarios/Scenario.py +90 -193
  150. edsl/scenarios/ScenarioHtmlMixin.py +4 -3
  151. edsl/scenarios/ScenarioList.py +415 -244
  152. edsl/scenarios/ScenarioListExportMixin.py +0 -7
  153. edsl/scenarios/ScenarioListPdfMixin.py +15 -37
  154. edsl/scenarios/__init__.py +1 -2
  155. edsl/scenarios/directory_scanner.py +96 -0
  156. edsl/scenarios/file_methods.py +85 -0
  157. edsl/scenarios/handlers/__init__.py +13 -0
  158. edsl/scenarios/handlers/csv.py +49 -0
  159. edsl/scenarios/handlers/docx.py +76 -0
  160. edsl/scenarios/handlers/html.py +37 -0
  161. edsl/scenarios/handlers/json.py +111 -0
  162. edsl/scenarios/handlers/latex.py +5 -0
  163. edsl/scenarios/handlers/md.py +51 -0
  164. edsl/scenarios/handlers/pdf.py +68 -0
  165. edsl/scenarios/handlers/png.py +39 -0
  166. edsl/scenarios/handlers/pptx.py +105 -0
  167. edsl/scenarios/handlers/py.py +294 -0
  168. edsl/scenarios/handlers/sql.py +313 -0
  169. edsl/scenarios/handlers/sqlite.py +149 -0
  170. edsl/scenarios/handlers/txt.py +33 -0
  171. edsl/scenarios/{ScenarioJoin.py → scenario_join.py} +10 -6
  172. edsl/scenarios/scenario_selector.py +156 -0
  173. edsl/study/ObjectEntry.py +1 -1
  174. edsl/study/SnapShot.py +1 -1
  175. edsl/study/Study.py +5 -12
  176. edsl/surveys/ConstructDAG.py +92 -0
  177. edsl/surveys/EditSurvey.py +221 -0
  178. edsl/surveys/InstructionHandler.py +100 -0
  179. edsl/surveys/MemoryManagement.py +72 -0
  180. edsl/surveys/Rule.py +5 -4
  181. edsl/surveys/RuleCollection.py +25 -27
  182. edsl/surveys/RuleManager.py +172 -0
  183. edsl/surveys/Simulator.py +75 -0
  184. edsl/surveys/Survey.py +270 -791
  185. edsl/surveys/SurveyCSS.py +20 -8
  186. edsl/surveys/{SurveyFlowVisualizationMixin.py → SurveyFlowVisualization.py} +11 -9
  187. edsl/surveys/SurveyToApp.py +141 -0
  188. edsl/surveys/__init__.py +4 -2
  189. edsl/surveys/descriptors.py +6 -2
  190. edsl/surveys/instructions/ChangeInstruction.py +1 -2
  191. edsl/surveys/instructions/Instruction.py +4 -13
  192. edsl/surveys/instructions/InstructionCollection.py +11 -6
  193. edsl/templates/error_reporting/interview_details.html +1 -1
  194. edsl/templates/error_reporting/report.html +1 -1
  195. edsl/tools/plotting.py +1 -1
  196. edsl/utilities/PrettyList.py +56 -0
  197. edsl/utilities/is_notebook.py +18 -0
  198. edsl/utilities/is_valid_variable_name.py +11 -0
  199. edsl/utilities/remove_edsl_version.py +24 -0
  200. edsl/utilities/utilities.py +35 -23
  201. {edsl-0.1.38.dev4.dist-info → edsl-0.1.39.dist-info}/METADATA +12 -10
  202. edsl-0.1.39.dist-info/RECORD +358 -0
  203. {edsl-0.1.38.dev4.dist-info → edsl-0.1.39.dist-info}/WHEEL +1 -1
  204. edsl/language_models/KeyLookup.py +0 -30
  205. edsl/language_models/registry.py +0 -190
  206. edsl/language_models/unused/ReplicateBase.py +0 -83
  207. edsl/results/ResultsDBMixin.py +0 -238
  208. edsl-0.1.38.dev4.dist-info/RECORD +0 -277
  209. /edsl/questions/{RegisterQuestionsMeta.py → register_questions_meta.py} +0 -0
  210. /edsl/results/{ResultsFetchMixin.py → results_fetch_mixin.py} +0 -0
  211. /edsl/results/{ResultsToolsMixin.py → results_tools_mixin.py} +0 -0
  212. {edsl-0.1.38.dev4.dist-info → edsl-0.1.39.dist-info}/LICENSE +0 -0
edsl/Base.py CHANGED
@@ -2,61 +2,22 @@
2
2
 
3
3
  from abc import ABC, abstractmethod, ABCMeta
4
4
  import gzip
5
- import io
6
5
  import json
7
6
  from typing import Any, Optional, Union
8
7
  from uuid import UUID
9
8
 
10
- # from edsl.utilities.MethodSuggesterMixin import MethodSuggesterMixin
11
-
12
- from edsl.utilities.utilities import is_notebook
13
-
14
-
15
- class RichPrintingMixin:
16
- pass
17
-
18
- # def print(self):
19
- # print(self)
20
-
21
-
22
- # """Mixin for rich printing and persistence of objects."""
23
-
24
- # def _for_console(self):
25
- # """Return a string representation of the object for console printing."""
26
- # from rich.console import Console
27
-
28
- # with io.StringIO() as buf:
29
- # console = Console(file=buf, record=True)
30
- # table = self.rich_print()
31
- # console.print(table)
32
- # return console.export_text()
33
-
34
- # def __str__(self):
35
- # """Return a string representation of the object for console printing."""
36
- # # return self._for_console()
37
- # return self.__repr__()
38
-
39
- # def print(self):
40
- # """Print the object to the console."""
41
- # from edsl.utilities.utilities import is_notebook
42
-
43
- # if is_notebook():
44
- # from IPython.display import display
45
-
46
- # display(self.rich_print())
47
- # else:
48
- # from rich.console import Console
49
-
50
- # console = Console()
51
- # console.print(self.rich_print())
52
-
53
9
 
54
10
  class PersistenceMixin:
55
11
  """Mixin for saving and loading objects to and from files."""
56
12
 
13
+ def duplicate(self, add_edsl_version=False):
14
+ """Return a duplicate of the object."""
15
+ return self.from_dict(self.to_dict(add_edsl_version=False))
16
+
57
17
  def push(
58
18
  self,
59
19
  description: Optional[str] = None,
20
+ alias: Optional[str] = None,
60
21
  visibility: Optional[str] = "unlisted",
61
22
  expected_parrot_url: Optional[str] = None,
62
23
  ):
@@ -64,7 +25,41 @@ class PersistenceMixin:
64
25
  from edsl.coop import Coop
65
26
 
66
27
  c = Coop(url=expected_parrot_url)
67
- return c.create(self, description, visibility)
28
+ return c.create(self, description, alias, visibility)
29
+
30
+ def to_yaml(self, add_edsl_version=False, filename: str = None) -> Union[str, None]:
31
+ import yaml
32
+
33
+ output = yaml.dump(self.to_dict(add_edsl_version=add_edsl_version))
34
+ if not filename:
35
+ return output
36
+
37
+ with open(filename, "w") as f:
38
+ f.write(output)
39
+
40
+ @classmethod
41
+ def from_yaml(cls, yaml_str: Optional[str] = None, filename: Optional[str] = None):
42
+ if yaml_str is None and filename is not None:
43
+ with open(filename, "r") as f:
44
+ yaml_str = f.read()
45
+ return cls.from_yaml(yaml_str=yaml_str)
46
+ elif yaml_str and filename is None:
47
+ import yaml
48
+
49
+ d = yaml.load(yaml_str, Loader=yaml.FullLoader)
50
+ return cls.from_dict(d)
51
+ else:
52
+ raise ValueError("Either yaml_str or filename must be provided.")
53
+
54
+ def create_download_link(self):
55
+ from tempfile import NamedTemporaryFile
56
+ from edsl.scenarios.FileStore import FileStore
57
+
58
+ with NamedTemporaryFile(suffix=".json.gz") as f:
59
+ self.save(f.name)
60
+ print(f.name)
61
+ fs = FileStore(path=f.name)
62
+ return fs.create_link()
68
63
 
69
64
  @classmethod
70
65
  def pull(
@@ -95,6 +90,7 @@ class PersistenceMixin:
95
90
  uuid: Optional[Union[str, UUID]] = None,
96
91
  url: Optional[str] = None,
97
92
  description: Optional[str] = None,
93
+ alias: Optional[str] = None,
98
94
  value: Optional[Any] = None,
99
95
  visibility: Optional[str] = None,
100
96
  ):
@@ -107,7 +103,7 @@ class PersistenceMixin:
107
103
  from edsl.coop import Coop
108
104
 
109
105
  coop = Coop()
110
- return coop.patch(uuid, url, description, value, visibility)
106
+ return coop.patch(uuid, url, description, alias, value, visibility)
111
107
 
112
108
  @classmethod
113
109
  def search(cls, query):
@@ -117,6 +113,13 @@ class PersistenceMixin:
117
113
  c = Coop()
118
114
  return c.search(cls, query)
119
115
 
116
+ def store(self, d: dict, key_name: Optional[str] = None):
117
+ if key_name is None:
118
+ index = len(d)
119
+ else:
120
+ index = key_name
121
+ d[index] = self
122
+
120
123
  def save(self, filename, compress=True):
121
124
  """Save the object to a file as zippped JSON.
122
125
 
@@ -126,15 +129,9 @@ class PersistenceMixin:
126
129
  if filename.endswith("json.gz"):
127
130
  import warnings
128
131
 
129
- # warnings.warn(
130
- # "Do not apply the file extensions. The filename should not end with 'json.gz'."
131
- # )
132
- filename = filename[:-7]
132
+ filename = filename[:-8]
133
133
  if filename.endswith("json"):
134
- filename = filename[:-4]
135
- # warnings.warn(
136
- # "Do not apply the file extensions. The filename should not end with 'json'."
137
- # )
134
+ filename = filename[:-5]
138
135
 
139
136
  if compress:
140
137
  full_file_name = filename + ".json.gz"
@@ -196,9 +193,15 @@ class RegisterSubclassesMeta(ABCMeta):
196
193
  RegisterSubclassesMeta._registry[cls.__name__] = cls
197
194
 
198
195
  @staticmethod
199
- def get_registry():
196
+ def get_registry(exclude_classes: Optional[list] = None):
200
197
  """Return the registry of subclasses."""
201
- return dict(RegisterSubclassesMeta._registry)
198
+ if exclude_classes is None:
199
+ exclude_classes = []
200
+ return {
201
+ k: v
202
+ for k, v in dict(RegisterSubclassesMeta._registry).items()
203
+ if k not in exclude_classes
204
+ }
202
205
 
203
206
 
204
207
  class DiffMethodsMixin:
@@ -209,45 +212,147 @@ class DiffMethodsMixin:
209
212
  return BaseDiff(self, other)
210
213
 
211
214
 
212
- class Base(
213
- # RichPrintingMixin,
214
- PersistenceMixin,
215
- DiffMethodsMixin,
216
- ABC,
217
- metaclass=RegisterSubclassesMeta,
218
- ):
219
- """Base class for all classes in the package."""
215
+ def is_iterable(obj):
216
+ try:
217
+ iter(obj)
218
+ except TypeError:
219
+ return False
220
+ return True
221
+
220
222
 
223
+ class RepresentationMixin:
221
224
  def json(self):
222
225
  return json.loads(json.dumps(self.to_dict(add_edsl_version=False)))
223
226
 
224
- def print(self, **kwargs):
225
- if "format" in kwargs:
226
- if kwargs["format"] not in ["html", "markdown", "rich", "latex"]:
227
- raise ValueError(f"Format '{kwargs['format']}' not supported.")
227
+ def to_dataset(self):
228
+ from edsl.results.Dataset import Dataset
229
+
230
+ return Dataset.from_edsl_object(self)
231
+
232
+ def view(self):
233
+ "Displays an interactive / perspective view of the object"
234
+ return self.to_dataset().view()
235
+
236
+ # def print(self, format="rich"):
237
+ # return self.to_dataset().table()
238
+
239
+ def display_dict(self):
240
+ display_dict = {}
241
+ d = self.to_dict(add_edsl_version=False)
242
+ for key, value in d.items():
243
+ if isinstance(value, dict):
244
+ for k, v in value.items():
245
+ display_dict[f"{key}:{k}"] = v
246
+ elif isinstance(value, list):
247
+ for i, v in enumerate(value):
248
+ display_dict[f"{key}:{i}"] = v
249
+ else:
250
+ display_dict[key] = value
251
+ return display_dict
252
+
253
+ def print(self, format="rich"):
254
+ from rich.table import Table
255
+ from rich.console import Console
256
+
257
+ table = Table(title=self.__class__.__name__)
258
+ table.add_column("Key", style="bold")
259
+ table.add_column("Value", style="bold")
260
+
261
+ for key, value in self.display_dict().items():
262
+ table.add_row(key, str(value))
263
+
264
+ console = Console(record=True)
265
+ console.print(table)
266
+
267
+ def help(obj):
268
+ """
269
+ Extract all public instance methods and their docstrings from a class instance.
270
+
271
+ Args:
272
+ obj: The instance to inspect
273
+
274
+ Returns:
275
+ dict: A dictionary where keys are method names and values are their docstrings
276
+ """
277
+ import inspect
278
+
279
+ if inspect.isclass(obj):
280
+ raise TypeError("Please provide a class instance, not a class")
281
+
282
+ methods = {}
283
+
284
+ # Get all members of the instance
285
+ for name, member in inspect.getmembers(obj):
286
+ # Skip private and special methods (those starting with underscore)
287
+ if name.startswith("_"):
288
+ continue
289
+
290
+ # Check if it's specifically an instance method
291
+ if inspect.ismethod(member):
292
+ # Get the docstring (or empty string if none exists)
293
+ docstring = inspect.getdoc(member) or ""
294
+ methods[name] = docstring
295
+
296
+ from edsl.results.Dataset import Dataset
297
+
298
+ d = Dataset(
299
+ [
300
+ {"method": list(methods.keys())},
301
+ {"documentation": list(methods.values())},
302
+ ]
303
+ )
304
+ return d
228
305
 
229
- if hasattr(self, "table"):
230
- return self.table()
306
+ def _repr_html_(self):
307
+ from edsl.results.TableDisplay import TableDisplay
308
+
309
+ if hasattr(self, "_summary"):
310
+ summary_dict = self._summary()
311
+ summary_line = "".join([f" {k}: {v};" for k, v in summary_dict.items()])
312
+ class_name = self.__class__.__name__
313
+ docs = getattr(self, "__documentation__", "")
314
+ return (
315
+ "<p>"
316
+ + f"<a href='{docs}'>{class_name}</a>"
317
+ + summary_line
318
+ + "</p>"
319
+ + self.table()._repr_html_()
320
+ )
231
321
  else:
232
- return self
322
+ class_name = self.__class__.__name__
323
+ documenation = getattr(self, "__documentation__", "")
324
+ summary_line = "<p>" + f"<a href='{documenation}'>{class_name}</a>" + "</p>"
325
+ display_dict = self.display_dict()
326
+ return (
327
+ summary_line
328
+ + TableDisplay.from_dictionary_wide(display_dict)._repr_html_()
329
+ )
233
330
 
234
331
  def __str__(self):
235
332
  return self.__repr__()
236
333
 
237
- def summary(self, format="table"):
238
- from edsl import Scenario
239
-
240
- d = self._summary()
241
- if format == "table":
242
- return Scenario(d).table()
243
- if format == "dict":
244
- return d
245
- if format == "json":
246
- return Scenario(d).json()
247
- if format == "yaml":
248
- return Scenario(d).yaml()
249
- if format == "html":
250
- return Scenario(d).table(tablefmt="html")
334
+
335
+ class HashingMixin:
336
+ def __hash__(self) -> int:
337
+ """Return a hash of the question."""
338
+ from edsl.utilities.utilities import dict_hash
339
+
340
+ return dict_hash(self.to_dict(add_edsl_version=False))
341
+
342
+ def __eq__(self, other):
343
+ """Return whether two objects are equal."""
344
+ return hash(self) == hash(other)
345
+
346
+
347
+ class Base(
348
+ RepresentationMixin,
349
+ PersistenceMixin,
350
+ DiffMethodsMixin,
351
+ HashingMixin,
352
+ ABC,
353
+ metaclass=RegisterSubclassesMeta,
354
+ ):
355
+ """Base class for all classes in the package."""
251
356
 
252
357
  def keys(self):
253
358
  """Return the keys of the object."""
@@ -264,42 +369,11 @@ class Base(
264
369
  keys = self.keys()
265
370
  return {data[key] for key in keys}
266
371
 
267
- def _repr_html_(self):
268
- from edsl.utilities.utilities import data_to_html
269
-
270
- return data_to_html(self.to_dict())
271
-
272
- # def html(self):
273
- # html_string = self._repr_html_()
274
- # import tempfile
275
- # import webbrowser
276
-
277
- # with tempfile.NamedTemporaryFile("w", delete=False, suffix=".html") as f:
278
- # # print("Writing HTML to", f.name)
279
- # f.write(html_string)
280
- # webbrowser.open(f.name)
281
-
282
- def __eq__(self, other):
283
- """Return whether two objects are equal."""
284
- import inspect
285
-
286
- if not isinstance(other, self.__class__):
287
- return False
288
- if "sort" in inspect.signature(self.to_dict).parameters:
289
- return self.to_dict(sort=True) == other.to_dict(sort=True)
290
- else:
291
- return self.to_dict() == other.to_dict()
292
-
293
372
  @abstractmethod
294
373
  def example():
295
374
  """This method should be implemented by subclasses."""
296
375
  raise NotImplementedError("This method is not implemented yet.")
297
376
 
298
- @abstractmethod
299
- def rich_print():
300
- """This method should be implemented by subclasses."""
301
- raise NotImplementedError("This method is not implemented yet.")
302
-
303
377
  @abstractmethod
304
378
  def to_dict():
305
379
  """This method should be implemented by subclasses."""
@@ -308,6 +382,13 @@ class Base(
308
382
  def to_json(self):
309
383
  return json.dumps(self.to_dict())
310
384
 
385
+ def store(self, d: dict, key_name: Optional[str] = None):
386
+ if key_name is None:
387
+ index = len(d)
388
+ else:
389
+ index = key_name
390
+ d[index] = self
391
+
311
392
  @abstractmethod
312
393
  def from_dict():
313
394
  """This method should be implemented by subclasses."""
edsl/__init__.py CHANGED
@@ -5,7 +5,9 @@ BASE_DIR = os.path.dirname(os.path.abspath(__file__))
5
5
  ROOT_DIR = os.path.dirname(BASE_DIR)
6
6
 
7
7
  from edsl.__version__ import __version__
8
- from edsl.config import Config, CONFIG
8
+
9
+ # from edsl.config import Config, CONFIG
10
+
9
11
  from edsl.agents.Agent import Agent
10
12
  from edsl.agents.AgentList import AgentList
11
13
 
@@ -18,6 +20,7 @@ from edsl.questions import QuestionFreeText
18
20
  from edsl.questions import QuestionFunctional
19
21
  from edsl.questions import QuestionLikertFive
20
22
  from edsl.questions import QuestionList
23
+ from edsl.questions import QuestionMatrix
21
24
  from edsl.questions import QuestionLinearScale
22
25
  from edsl.questions import QuestionNumerical
23
26
  from edsl.questions import QuestionYesNo
@@ -25,22 +28,27 @@ from edsl.questions import QuestionBudget
25
28
  from edsl.questions import QuestionRank
26
29
  from edsl.questions import QuestionTopK
27
30
 
28
- from edsl.scenarios import Scenario
29
- from edsl.scenarios import ScenarioList
31
+ from edsl.scenarios.Scenario import Scenario
32
+ from edsl.scenarios.ScenarioList import ScenarioList
30
33
  from edsl.scenarios.FileStore import FileStore
31
34
 
32
35
  # from edsl.utilities.interface import print_dict_with_rich
33
36
  from edsl.surveys.Survey import Survey
34
- from edsl.language_models.registry import Model
37
+ from edsl.language_models.model import Model
35
38
  from edsl.language_models.ModelList import ModelList
39
+
36
40
  from edsl.results.Results import Results
37
41
  from edsl.data.Cache import Cache
38
- from edsl.data.CacheEntry import CacheEntry
42
+
43
+ # from edsl.data.CacheEntry import CacheEntry
39
44
  from edsl.data.CacheHandler import set_session_cache, unset_session_cache
40
- from edsl.shared import shared_globals
45
+
46
+ # from edsl.shared import shared_globals
47
+
41
48
  from edsl.jobs.Jobs import Jobs
42
49
  from edsl.notebooks.Notebook import Notebook
43
- from edsl.study.Study import Study
50
+
51
+ # from edsl.study.Study import Study
44
52
 
45
53
  # from edsl.conjure.Conjure import Conjure
46
54
  from edsl.coop.coop import Coop
edsl/__version__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.38.dev4"
1
+ __version__ = "0.1.39"