revisit 0.0.3__py2.py3-none-any.whl → 0.0.4__py2.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.
revisit/__init__.py CHANGED
@@ -1,54 +1,8 @@
1
- import importlib.metadata
2
- import pathlib
3
- import anywidget
4
- import traitlets
1
+ # Import main functions from core.py
2
+ from . import revisit
5
3
 
6
- try:
7
- __version__ = importlib.metadata.version("revisit_notebook_widget")
8
- except importlib.metadata.PackageNotFoundError:
9
- __version__ = "unknown"
4
+ # Import the Widget class from widget.py
5
+ from .widget import Widget
10
6
 
11
-
12
-
13
- # class Widget2(anywidget.AnyWidget):
14
-
15
- class TestWidget(anywidget.AnyWidget):
16
- _esm = """
17
- function render({ model, el }) {
18
- let button = document.createElement("button");
19
- button.innerHTML = `count is ${model.get("value")}`;
20
- button.addEventListener("click", () => {
21
- model.set("value", model.get("value") + 1);
22
- model.save_changes();
23
- });
24
- model.on("change:value", () => {
25
- button.innerHTML = `count is ${model.get("value")}`;
26
- });
27
- el.classList.add("counter-widget");
28
- el.appendChild(button);
29
- }
30
- export default { render };
31
- """
32
- _css = """
33
- .counter-widget button { color: white; font-size: 1.75rem; background-color: #ea580c; padding: 0.5rem 1rem; border: none; border-radius: 0.25rem; }
34
- .counter-widget button:hover { background-color: #9a3412; }
35
- """
36
- value = traitlets.Int(0).tag(sync=True)
37
-
38
-
39
-
40
- class Widget(anywidget.AnyWidget):
41
- _esm = pathlib.Path(__file__).parent / "static" / "widget.js"
42
- _css = pathlib.Path(__file__).parent / "static" / "widget.css"
43
- # value = traitlets.Int(0).tag(sync=True)
44
- config = traitlets.Dict({}).tag(sync=True)
45
- sequence = traitlets.List([]).tag(sync=True)
46
- internalWidget = TestWidget()
47
-
48
- @traitlets.observe('sequence')
49
- def _sequence_changed(self, change):
50
- self.internalWidget.value += 1
51
- # internalWidget.value += 1
52
- # print("{name} changed from {old} to {new}".format(**change))
53
-
54
-
7
+ # Expose them in the package's namespace
8
+ __all__ = [*revisit.__all__, "Widget"]
revisit/widget.py ADDED
@@ -0,0 +1,49 @@
1
+ import importlib.metadata
2
+ import pathlib
3
+ import anywidget # type: ignore
4
+ import traitlets # type: ignore
5
+
6
+ try:
7
+ __version__ = importlib.metadata.version("revisit_notebook_widget")
8
+ except importlib.metadata.PackageNotFoundError:
9
+ __version__ = "unknown"
10
+
11
+
12
+ # class Widget2(anywidget.AnyWidget):
13
+ class TestWidget(anywidget.AnyWidget):
14
+ _esm = """
15
+ function render({ model, el }) {
16
+ let button = document.createElement("button");
17
+ button.innerHTML = `count is ${model.get("value")}`;
18
+ button.addEventListener("click", () => {
19
+ model.set("value", model.get("value") + 1);
20
+ model.save_changes();
21
+ });
22
+ model.on("change:value", () => {
23
+ button.innerHTML = `count is ${model.get("value")}`;
24
+ });
25
+ el.classList.add("counter-widget");
26
+ el.appendChild(button);
27
+ }
28
+ export default { render };
29
+ """
30
+ _css = """
31
+ .counter-widget button { color: white; font-size: 1.75rem; background-color: #ea580c; padding: 0.5rem 1rem; border: none; border-radius: 0.25rem; }
32
+ .counter-widget button:hover { background-color: #9a3412; }
33
+ """
34
+ value = traitlets.Int(0).tag(sync=True)
35
+
36
+
37
+ class Widget(anywidget.AnyWidget):
38
+ _esm = pathlib.Path(__file__).parent / "static" / "widget.js"
39
+ _css = pathlib.Path(__file__).parent / "static" / "widget.css"
40
+ # value = traitlets.Int(0).tag(sync=True)
41
+ config = traitlets.Dict({}).tag(sync=True)
42
+ sequence = traitlets.List([]).tag(sync=True)
43
+ internalWidget = TestWidget()
44
+
45
+ @traitlets.observe('sequence')
46
+ def _sequence_changed(self, change):
47
+ self.internalWidget.value += 1
48
+ # internalWidget.value += 1
49
+ # print("{name} changed from {old} to {new}".format(**change))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: revisit
3
- Version: 0.0.3
3
+ Version: 0.0.4
4
4
  Requires-Dist: anywidget
5
5
  Requires-Dist: ipykernel>=6.29.5
6
6
  Requires-Dist: pydantic>=2.10.5
@@ -0,0 +1,9 @@
1
+ revisit/__init__.py,sha256=HlkO6ZGRm7gql0cU-oQvXTbcXGBdc0ck3yvuzu7_JX8,209
2
+ revisit/models.py,sha256=c-Hsd6XqeIP-hybH6MUovHG65XXueRhaMEVJZW1ViX0,120701
3
+ revisit/revisit.py,sha256=ChFtPmdXR8WPtSoUz9-NfvOcLVutSIJWUoWYxdhTE6o,19167
4
+ revisit/widget.py,sha256=ih0XhRjkih8vpeDr1SO8l8zMydZHLSXxVaFzvA8up_8,1722
5
+ revisit/static/widget.css,sha256=TLu5F6k0CvowQtmApPswG-JZUXYszo7a10dVWKnZsIg,647
6
+ revisit/static/widget.js,sha256=MlZ2jHlh_ADsUKMC5nZaSAmW73-4y2B57NcS3E5Jh3Q,187153
7
+ revisit-0.0.4.dist-info/METADATA,sha256=uzoyn8KDCUHZpGeHNgIRDC5i1so4Wr6qyfLO1H8tk9A,1261
8
+ revisit-0.0.4.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
9
+ revisit-0.0.4.dist-info/RECORD,,
@@ -1,521 +0,0 @@
1
- from __future__ import annotations
2
- import json
3
- from . import models as rvt_models
4
- from pydantic import BaseModel, ValidationError # type: ignore
5
- from typing import List, Literal, get_origin, Optional, get_args, Any, Unpack, overload, get_type_hints
6
- from enum import Enum
7
- import csv
8
- from dataclasses import make_dataclass
9
- import re
10
-
11
-
12
- class _JSONableBaseModel(BaseModel):
13
- def __str__(self):
14
- return json.dumps(
15
- json.loads(
16
- self.root.model_dump_json(
17
- exclude_none=True, by_alias=True
18
- )),
19
- indent=4
20
- )
21
-
22
-
23
- # Private
24
- class _WrappedResponse(_JSONableBaseModel):
25
- root: rvt_models.Response
26
-
27
- def model_post_init(self, __context: Any) -> None:
28
- # Sets the root to be the instantiation of the individual response type instead
29
- # of the union response type
30
- self.root = self.root.root
31
-
32
- def set(self, overwrite=True, **kwargs) -> _WrappedResponse:
33
- for key, value in kwargs.items():
34
- # Disallow changing type
35
- if key == 'type':
36
- if getattr(self.root, key) != value:
37
- raise RevisitError(message=f"Cannot change type from {getattr(self.root, key)} to {value}")
38
- elif key != 'base':
39
- if overwrite is True or (overwrite is False and getattr(self.root, key) is None):
40
- setattr(self.root, key, value)
41
-
42
- # Re-validates the model. Returns the new model.
43
- self.root = _validate_response(self.root.__dict__)
44
- return self
45
-
46
-
47
- # Private
48
- class _WrappedComponent(_JSONableBaseModel):
49
- component_name__: str
50
- base__: Optional[_WrappedComponent] = None
51
- context__: Optional[dict] = None
52
- root: rvt_models.IndividualComponent
53
-
54
- def model_post_init(self, __context: Any) -> None:
55
- # Sets the root to be the instantiation of the individual response type instead
56
- # of the union response type
57
- self.root = self.root.root
58
-
59
- def responses(self, responses: List[_WrappedResponse]) -> _WrappedComponent:
60
- for item in responses:
61
- if not isinstance(item, _WrappedResponse):
62
- raise ValueError(f'Expecting type Response got {type(item)}')
63
- self.root.response = responses
64
- return self
65
-
66
- def get_response(self, id: str) -> _WrappedResponse | None:
67
- for response in self.root.response:
68
- if response.root.id == id:
69
- return response
70
- return None
71
-
72
- def edit_response(self, id: str, **kwargs) -> _WrappedComponent:
73
- for response in self.root.response:
74
- if response.root.id == id:
75
- response.set(**kwargs)
76
- return self
77
-
78
- raise ValueError('No response with given ID found.')
79
-
80
- def response_context(self, **kwargs):
81
- self.context__ = kwargs
82
-
83
- for type, data in self.context__.items():
84
- for response in self.root.response:
85
- if response.root.type == type or type == 'all':
86
- response.set(
87
- overwrite=False,
88
- **data
89
- )
90
-
91
- return self
92
-
93
-
94
- class _WrappedStudyMetadata(_JSONableBaseModel):
95
- root: rvt_models.StudyMetadata
96
-
97
-
98
- class _WrappedUIConfig(_JSONableBaseModel):
99
- root: rvt_models.UIConfig
100
-
101
-
102
- class _WrappedComponentBlock(_JSONableBaseModel):
103
- root: rvt_models.ComponentBlock
104
- component_objects__: List[_WrappedComponent]
105
-
106
- def __add__(self, other):
107
- """Allows addition operator to append to sequence components list."""
108
- if isinstance(other, _WrappedComponentBlock) or isinstance(other, _WrappedComponent):
109
- self.component_objects__.append(other)
110
- self.root.components.append(other.component_name__)
111
- return self
112
- return NotImplemented
113
-
114
- def from_data(self, data_list: list):
115
- return DataIterator(data_list, self)
116
-
117
-
118
- class _WrappedStudyConfig(_JSONableBaseModel):
119
- root: rvt_models.StudyConfig
120
-
121
-
122
- class _StudyConfigType(rvt_models.StudyConfigType):
123
- components: List[_WrappedComponent]
124
-
125
-
126
- class DataIterator:
127
- def __init__(self, data_list: List, parent_class: _WrappedComponentBlock):
128
- self.data = data_list
129
- self.parent_class = parent_class
130
-
131
- def component(self, **kwargs):
132
- for datum in self.data:
133
- current_dict = {}
134
- for key, value in kwargs.items():
135
- if key == 'parameters':
136
- param_dict = {}
137
- for param_key, param_value in value.items():
138
- if type(param_value) is str:
139
- param_datum_value = _extract_datum_value(param_value)
140
- if param_datum_value is not None:
141
- param_dict[param_key] = getattr(datum, param_datum_value)
142
- else:
143
- param_dict[param_key] = value
144
- else:
145
- param_dict[param_key] = value
146
- current_dict[key] = param_dict
147
- else:
148
- if type(value) is str:
149
- datum_value = _extract_datum_value(value)
150
- if datum_value is not None:
151
- if key == 'component_name__':
152
- current_dict[key] = str(getattr(datum, datum_value))
153
- else:
154
- current_dict[key] = getattr(datum, datum_value)
155
- else:
156
- current_dict[key] = value
157
- else:
158
- current_dict[key] = value
159
- curr_component = component(**current_dict)
160
- self.parent_class = self.parent_class + curr_component
161
- # Return the parent class calling iterator when component is finished.
162
- return self.parent_class
163
-
164
-
165
- # # -----------------------------------
166
- # # Factory Functions
167
- # # -----------------------------------
168
-
169
- # Component factory function
170
- # Allows additional items to be sent over to our Component model while keeping restrictions
171
- # for the model that is auto-generated.
172
-
173
- @overload
174
- def component(**kwargs: Unpack[rvt_models.MarkdownComponentType]) -> _WrappedComponent: ...
175
- @overload
176
- def component(**kwargs: Unpack[rvt_models.ReactComponentType]) -> _WrappedComponent: ...
177
- @overload
178
- def component(**kwargs: Unpack[rvt_models.ImageComponentType]) -> _WrappedComponent: ...
179
- @overload
180
- def component(**kwargs: Unpack[rvt_models.WebsiteComponentType]) -> _WrappedComponent: ...
181
- @overload
182
- def component(**kwargs: Unpack[rvt_models.QuestionnaireComponentType]) -> _WrappedComponent: ...
183
- @overload
184
- def component(**kwargs: Any) -> _WrappedComponent: ...
185
-
186
-
187
- def component(**kwargs) -> _WrappedComponent:
188
- # Inherit base
189
- base_component = kwargs.get('base__', None)
190
- if base_component:
191
- base_fields = vars(base_component.root)
192
- for key, value in base_fields.items():
193
- if key not in kwargs:
194
- kwargs[key] = value
195
- # Get kwargs to pass to individual component
196
- filter_kwargs = _get_filtered_kwargs(rvt_models.IndividualComponent, kwargs)
197
- # Grab response list
198
- response = filter_kwargs.get('response')
199
-
200
- # Sets default response list
201
- valid_response = []
202
- # If response present
203
- if response is not None:
204
- for r in response:
205
-
206
- # Prevent dict input
207
- if isinstance(r, dict):
208
- raise RevisitError(message='Cannot pass a dictionary directly into "Response" list.')
209
-
210
- response_type_hint = get_type_hints(rvt_models.Response).get('root')
211
- response_types = get_args(response_type_hint)
212
-
213
- # If wrapped, get root
214
- if isinstance(r, _WrappedResponse):
215
- valid_response.append(r.root)
216
-
217
- # If not wrapped but is valid response, append to list
218
- elif r.__class__ in response_types:
219
- valid_response.append(r)
220
-
221
- # If other unknown type, raise error
222
- else:
223
- raise RevisitError(message=f'Invalid type {type(r)} for "Response" class.')
224
-
225
- filter_kwargs['response'] = valid_response
226
-
227
- # Validate component
228
- _validate_component(filter_kwargs)
229
- base_model = rvt_models.IndividualComponent(**filter_kwargs)
230
-
231
- try:
232
- return _WrappedComponent(**kwargs, root=base_model)
233
- except ValidationError as e:
234
- raise RevisitError(e.errors())
235
-
236
-
237
- # Response factory function
238
- @overload
239
- def response(**kwargs: Unpack[rvt_models.NumericalResponseType]) -> _WrappedResponse: ...
240
- @overload
241
- def response(**kwargs: Unpack[rvt_models.ShortTextResponseType]) -> _WrappedResponse: ...
242
- @overload
243
- def response(**kwargs: Unpack[rvt_models.LongTextResponseType]) -> _WrappedResponse: ...
244
- @overload
245
- def response(**kwargs: Unpack[rvt_models.LikertResponseType]) -> _WrappedResponse: ...
246
- @overload
247
- def response(**kwargs: Unpack[rvt_models.DropdownResponseType]) -> _WrappedResponse: ...
248
- @overload
249
- def response(**kwargs: Unpack[rvt_models.SliderResponseType]) -> _WrappedResponse: ...
250
- @overload
251
- def response(**kwargs: Unpack[rvt_models.RadioResponseType]) -> _WrappedResponse: ...
252
- @overload
253
- def response(**kwargs: Unpack[rvt_models.CheckboxResponseType]) -> _WrappedResponse: ...
254
- @overload
255
- def response(**kwargs: Unpack[rvt_models.IFrameResponseType]) -> _WrappedResponse: ...
256
- @overload
257
- def response(**kwargs: Unpack[rvt_models.MatrixResponseType]) -> _WrappedResponse: ...
258
- @overload
259
- def response(**kwargs: Any) -> _WrappedResponse: ...
260
-
261
-
262
- def response(**kwargs) -> _WrappedResponse:
263
- filter_kwargs = _get_filtered_kwargs(rvt_models.Response, kwargs)
264
- _validate_response(filter_kwargs)
265
- base_model = rvt_models.Response(**filter_kwargs)
266
- # We've validated the response for a particular type. Now, how do we validate the wrapped component correctly?
267
- try:
268
- return _WrappedResponse(**kwargs, root=base_model)
269
- except ValidationError as e:
270
- raise RevisitError(e.errors())
271
-
272
-
273
- def studyMetadata(**kwargs: Unpack[rvt_models.StudyMetadataType]):
274
- filter_kwargs = _get_filtered_kwargs(rvt_models.StudyMetadata, kwargs)
275
- base_model = rvt_models.StudyMetadata(**filter_kwargs)
276
- return _WrappedStudyMetadata(**kwargs, root=base_model)
277
-
278
-
279
- def uiConfig(**kwargs: Unpack[rvt_models.UIConfigType]):
280
- filter_kwargs = _get_filtered_kwargs(rvt_models.UIConfig, kwargs)
281
- base_model = rvt_models.UIConfig(**filter_kwargs)
282
- return _WrappedUIConfig(**kwargs, root=base_model)
283
-
284
-
285
- def sequence(**kwargs: Unpack[rvt_models.ComponentBlockType]):
286
- filter_kwargs = _get_filtered_kwargs(rvt_models.ComponentBlock, kwargs)
287
- valid_component_names = []
288
- valid_components = []
289
- components = filter_kwargs.get('components')
290
- if components is not None:
291
- for c in components:
292
-
293
- # Prevent dict input
294
- if isinstance(c, dict):
295
- raise RevisitError(message='Cannot pass a dictionary directly into "Component" list.')
296
-
297
- # If wrapped, get root
298
- if isinstance(c, _WrappedComponent):
299
- valid_component_names.append(c.component_name__)
300
- valid_components.append(c)
301
-
302
- # If other unknown type, raise error
303
- else:
304
- raise RevisitError(message=f'Invalid type {type(c)} for "Component" class.')
305
-
306
- filter_kwargs['components'] = valid_component_names
307
- base_model = rvt_models.ComponentBlock(**filter_kwargs)
308
- return _WrappedComponentBlock(**kwargs, root=base_model, component_objects__=valid_components)
309
-
310
-
311
- @overload
312
- def studyConfig(**kwargs: Unpack[_StudyConfigType]) -> _WrappedStudyConfig: ...
313
- @overload
314
- def studyConfig(**kwargs: Any) -> _WrappedStudyConfig: ...
315
-
316
-
317
- def studyConfig(**kwargs: Unpack[_StudyConfigType]) -> _WrappedStudyConfig:
318
- filter_kwargs = _get_filtered_kwargs(rvt_models.StudyConfig, kwargs)
319
-
320
- root_list = ['studyMetadata', 'uiConfig', 'sequence']
321
- un_rooted_kwargs = {x: (y.root if x in root_list and hasattr(y, 'root') else y) for x, y in filter_kwargs.items()}
322
-
323
- study_sequence = filter_kwargs['sequence']
324
-
325
- # Merges components from the components list given and the components that are stored in the sequence
326
- un_rooted_kwargs['components'] = {
327
- comp.component_name__: comp.root for comp in un_rooted_kwargs.get('components', [])
328
- } | {
329
- comp.component_name__: comp.root for comp in study_sequence.component_objects__
330
- }
331
-
332
- base_model = rvt_models.StudyConfig(**un_rooted_kwargs)
333
- return _WrappedStudyConfig(**kwargs, root=base_model)
334
-
335
-
336
- # Function to parse the CSV and dynamically create data classes
337
- def data(file_path: str) -> List[Any]:
338
- # Read the first row to get the headers
339
- with open(file_path, mode='r') as csvfile:
340
- csv_reader = csv.DictReader(csvfile)
341
- headers = csv_reader.fieldnames
342
- if not headers:
343
- raise RevisitError(message="No headers found in CSV file.")
344
-
345
- # Create a data class with attributes based on the headers
346
- DataRow = make_dataclass("DataRow", [(header, Any) for header in headers])
347
-
348
- # Parse each row into an instance of the dynamically created data class
349
- data_rows = []
350
- for row in csv_reader:
351
- # Convert the row values to the appropriate types (e.g., int, float, bool)
352
- data = {key: _convert_value(value) for key, value in row.items()}
353
- data_row = DataRow(**data)
354
- data_rows.append(data_row)
355
-
356
- return data_rows
357
-
358
-
359
- # ------- PRIVATE FUNCTIONS ------------ #
360
-
361
- def _validate_component(kwargs: dict):
362
- component_mapping = _generate_possible_component_types()[1]
363
- if 'type' not in kwargs:
364
- raise RevisitError(message='"Type" is required on Component.')
365
- elif component_mapping.get(kwargs['type']) is None:
366
- raise RevisitError(message=f'Unexpected component type: {kwargs['type']}')
367
-
368
- try:
369
- return rvt_models.IndividualComponent.model_validate(kwargs).root
370
- except ValidationError as e:
371
- temp_errors = []
372
-
373
- for entry in e.errors():
374
- if entry['loc'][0] == component_mapping[kwargs['type']]:
375
- temp_errors.append(entry)
376
-
377
- if len(temp_errors) > 0:
378
- raise RevisitError(temp_errors)
379
- else:
380
- raise RevisitError(
381
- message='Unexpected error occurred during Component instantiation.'
382
- )
383
-
384
-
385
- # Call validate response when creating response component.
386
- def _validate_response(kwargs: dict):
387
- response_mapping = _generate_possible_response_types()[1]
388
- if 'type' not in kwargs:
389
- raise RevisitError(message='"Type" is required on Response.')
390
- else:
391
-
392
- type_value = kwargs.get('type')
393
-
394
- # Handles enum class type
395
- if isinstance(kwargs.get('type'), Enum):
396
- type_value = type_value.value
397
-
398
- if response_mapping.get(type_value) is None:
399
- raise RevisitError(message=f'Unexpected type: {type_value}')
400
-
401
- try:
402
- return rvt_models.Response.model_validate(kwargs).root
403
- except ValidationError as e:
404
- temp_errors = []
405
- for entry in e.errors():
406
- if entry['loc'][0] == response_mapping[type_value]:
407
- temp_errors.append(entry)
408
-
409
- if len(temp_errors) > 0:
410
- raise RevisitError(temp_errors)
411
- else:
412
- raise RevisitError(
413
- message='Unexpected error occurred during Response instantiation'
414
- )
415
-
416
-
417
- def _generate_possible_response_types():
418
- return _generate_possible_types(rvt_models.Response)
419
-
420
-
421
- def _generate_possible_component_types():
422
- return _generate_possible_types(rvt_models.IndividualComponent)
423
-
424
-
425
- # Generates mappings between the response class name and the
426
- # type string literal. Creates the reversed mapping as well.
427
- def _generate_possible_types(orig_cls):
428
- response_type_hint = get_type_hints(orig_cls).get('root')
429
- response_types = get_args(response_type_hint)
430
- type_hints = {}
431
- type_hints_reversed = {}
432
- for cls in response_types:
433
- curr_type = get_type_hints(cls).get('type')
434
- curr_origin = get_origin(get_type_hints(cls).get('type'))
435
- if curr_origin is Literal:
436
- type_hints[cls.__name__] = set([get_args(curr_type)[0]])
437
- type_hints_reversed[get_args(curr_type)[0]] = cls.__name__
438
- elif isinstance(curr_type, type) and issubclass(curr_type, Enum):
439
- enum_list = [member.value for member in curr_type]
440
- type_hints[cls.__name__] = set(enum_list)
441
- for item in enum_list:
442
- type_hints_reversed[item] = cls.__name__
443
-
444
- return (type_hints, type_hints_reversed)
445
-
446
-
447
- # Custom exception
448
- class RevisitError(Exception):
449
- def __init__(self, errors=None, message=None):
450
- # Case 1: Validation Errors From Pydantic
451
- # Case 2: Standard Error Message
452
- super().__init__('There was an error.')
453
- if message is None:
454
- pretty_message_list = pretty_error(errors)
455
- self.message = \
456
- f'There was an error. \n' \
457
- f'----------------------------------------------------' \
458
- f'\n\n' \
459
- f'{'\n\n'.join(pretty_message_list)}' \
460
- f'\n'
461
- else:
462
- self.message = \
463
- f'There was an error. \n' \
464
- f'----------------------------------------------------' \
465
- f'\n\n' \
466
- f'{message}' \
467
- f'\n'
468
-
469
- def __str__(self):
470
- return self.message
471
-
472
-
473
- def pretty_error(errors):
474
- custom_messages = {
475
- 'missing': 'Field is missing'
476
- }
477
- new_error_messages = []
478
- for error in errors:
479
- custom_message = custom_messages.get(error['type'])
480
- if custom_message:
481
- new_error_messages.append(f'Location: {error['loc']}\nError: Field "{error['loc'][-1]}" is required.')
482
- else:
483
- new_error_messages.append(f'Location: {error['loc']}\nError: {error['msg']}')
484
- return new_error_messages
485
-
486
-
487
- def _get_filtered_kwargs(class_type: Any, kwargs):
488
- try:
489
- possible_items = get_args(class_type.__fields__.get('root').annotation)
490
- except AttributeError:
491
- possible_items = [class_type]
492
-
493
- valid_fields = set()
494
- for model in possible_items:
495
- valid_fields.update(model.model_fields.keys())
496
-
497
- return {key: value for key, value in kwargs.items() if key in valid_fields}
498
-
499
-
500
- def _convert_value(value: str) -> Any:
501
- """Helper function to convert string values to appropriate data types."""
502
- value = value.strip()
503
- if value.lower() == "true":
504
- return True
505
- elif value.lower() == "false":
506
- return False
507
- try:
508
- if '.' in value:
509
- return float(value)
510
- else:
511
- return int(value)
512
- except ValueError:
513
- return value # Return as string if it cannot be converted
514
-
515
-
516
- def _extract_datum_value(text: str) -> str:
517
- # Use regex to match 'datum:thing' and capture 'thing'
518
- match = re.match(r'^datum:(\w+)$', text)
519
- if match:
520
- return match.group(1) # Return the captured part (i.e., 'thing')
521
- return None # Return None if the pattern doesn't match
@@ -1,9 +0,0 @@
1
- revisit/__init__.py,sha256=cDMK5FstjH7vrZQZabUmcZwpB3-hTZMHatVUu2gdKr0,1702
2
- revisit/revisit/__init__.py,sha256=7rhJeSoVZkNSNXUVHRIFQxkuxDUn_dtcjXnC2DQLtuk,19174
3
- revisit/revisit/models.py,sha256=c-Hsd6XqeIP-hybH6MUovHG65XXueRhaMEVJZW1ViX0,120701
4
- revisit/revisit/revisit.py,sha256=ChFtPmdXR8WPtSoUz9-NfvOcLVutSIJWUoWYxdhTE6o,19167
5
- revisit/static/widget.css,sha256=TLu5F6k0CvowQtmApPswG-JZUXYszo7a10dVWKnZsIg,647
6
- revisit/static/widget.js,sha256=MlZ2jHlh_ADsUKMC5nZaSAmW73-4y2B57NcS3E5Jh3Q,187153
7
- revisit-0.0.3.dist-info/METADATA,sha256=FF8AyslwC22_3OXEjXA1ZfE4yjzM1PsRbxx-zn6UHHo,1261
8
- revisit-0.0.3.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
9
- revisit-0.0.3.dist-info/RECORD,,
File without changes
File without changes