revisit 0.0.6__py2.py3-none-any.whl → 0.0.8__py2.py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
revisit/revisit.py
CHANGED
@@ -7,6 +7,10 @@ from enum import Enum
|
|
7
7
|
import csv
|
8
8
|
from dataclasses import make_dataclass
|
9
9
|
import re
|
10
|
+
import os
|
11
|
+
import shutil
|
12
|
+
from . import widget as _widget
|
13
|
+
|
10
14
|
|
11
15
|
__all__ = [
|
12
16
|
"component",
|
@@ -15,7 +19,8 @@ __all__ = [
|
|
15
19
|
"uiConfig",
|
16
20
|
"studyMetadata",
|
17
21
|
"studyConfig",
|
18
|
-
"data"
|
22
|
+
"data",
|
23
|
+
"widget"
|
19
24
|
]
|
20
25
|
|
21
26
|
|
@@ -53,6 +58,9 @@ class _WrappedResponse(_JSONableBaseModel):
|
|
53
58
|
self.root = _validate_response(self.root.__dict__)
|
54
59
|
return self
|
55
60
|
|
61
|
+
def clone(self):
|
62
|
+
return response(**self.root.__dict__)
|
63
|
+
|
56
64
|
|
57
65
|
# Private
|
58
66
|
class _WrappedComponent(_JSONableBaseModel):
|
@@ -80,9 +88,20 @@ class _WrappedComponent(_JSONableBaseModel):
|
|
80
88
|
return None
|
81
89
|
|
82
90
|
def edit_response(self, id: str, **kwargs) -> _WrappedComponent:
|
83
|
-
|
84
|
-
|
85
|
-
|
91
|
+
print(self.root.response)
|
92
|
+
for r in self.root.response:
|
93
|
+
if r.root.id == id:
|
94
|
+
# Get dict
|
95
|
+
response_dict = r.root.__dict__
|
96
|
+
# Create new response
|
97
|
+
new_response = response(**response_dict)
|
98
|
+
# Set with new values
|
99
|
+
new_response.set(**kwargs)
|
100
|
+
# Filter out old response
|
101
|
+
self.root.response = [_r for _r in self.root.response if _r.root.id != id]
|
102
|
+
# Add new response
|
103
|
+
self.root.response.append(new_response)
|
104
|
+
# Return component
|
86
105
|
return self
|
87
106
|
|
88
107
|
raise ValueError('No response with given ID found.')
|
@@ -100,6 +119,9 @@ class _WrappedComponent(_JSONableBaseModel):
|
|
100
119
|
|
101
120
|
return self
|
102
121
|
|
122
|
+
def clone(self, component_name__):
|
123
|
+
return component(**self.root.__dict__, component_name__=component_name__)
|
124
|
+
|
103
125
|
|
104
126
|
class _WrappedStudyMetadata(_JSONableBaseModel):
|
105
127
|
root: rvt_models.StudyMetadata
|
@@ -115,13 +137,24 @@ class _WrappedComponentBlock(_JSONableBaseModel):
|
|
115
137
|
|
116
138
|
def __add__(self, other):
|
117
139
|
"""Allows addition operator to append to sequence components list."""
|
118
|
-
if isinstance(other,
|
140
|
+
if isinstance(other, _WrappedComponent):
|
119
141
|
self.component_objects__.append(other)
|
120
142
|
self.root.components.append(other.component_name__)
|
121
143
|
return self
|
144
|
+
elif isinstance(other, _WrappedComponentBlock):
|
145
|
+
# Extend existing list of components with new set of components for tracking
|
146
|
+
self.component_objects__.extend(other.component_objects__)
|
147
|
+
|
148
|
+
# Add root object to components
|
149
|
+
self.root.components.append(other.root)
|
150
|
+
return self
|
122
151
|
return NotImplemented
|
123
152
|
|
124
|
-
def from_data(self, data_list
|
153
|
+
def from_data(self, data_list) -> DataIterator:
|
154
|
+
if not isinstance(data_list, list):
|
155
|
+
raise RevisitError(
|
156
|
+
message="'from_data' must take in a list of data rows. Use reVISit's 'data' method to parse a CSV file into a valid input."
|
157
|
+
)
|
125
158
|
return DataIterator(data_list, self)
|
126
159
|
|
127
160
|
|
@@ -366,6 +399,67 @@ def data(file_path: str) -> List[Any]:
|
|
366
399
|
return data_rows
|
367
400
|
|
368
401
|
|
402
|
+
def widget(study: _WrappedStudyConfig, revisitPath: str):
|
403
|
+
if not os.path.isdir(revisitPath):
|
404
|
+
raise RevisitError(message=f'"{revisitPath}" does not exist.')
|
405
|
+
|
406
|
+
extracted_paths = []
|
407
|
+
|
408
|
+
for component in study.root.components.values():
|
409
|
+
if hasattr(component.root, 'path'):
|
410
|
+
|
411
|
+
fileName = component.root.path.split('/')[-1]
|
412
|
+
|
413
|
+
if component.root.type == 'react-component':
|
414
|
+
dest = f"{revisitPath}/src/public/__revisit-widget/assets/{fileName}"
|
415
|
+
else:
|
416
|
+
dest = f"{revisitPath}/public/__revisit-widget/assets/{fileName}"
|
417
|
+
|
418
|
+
extracted_paths.append({
|
419
|
+
"src": component.root.path,
|
420
|
+
"dest": dest
|
421
|
+
})
|
422
|
+
|
423
|
+
newPath = f"__revisit-widget/assets/{fileName}"
|
424
|
+
component.root.path = newPath
|
425
|
+
|
426
|
+
uiConfig = study.root.uiConfig
|
427
|
+
if uiConfig.helpTextPath is not None:
|
428
|
+
|
429
|
+
fileName = uiConfig.helpTextPath.split('/')[-1]
|
430
|
+
dest = f"{revisitPath}/public/__revisit-widget/assets/{fileName}"
|
431
|
+
|
432
|
+
extracted_paths.append({
|
433
|
+
"src": uiConfig.helpTextPath,
|
434
|
+
"dest": dest
|
435
|
+
})
|
436
|
+
|
437
|
+
newPath = f"__revisit-widget/assets/{fileName}"
|
438
|
+
uiConfig.helpTextPath = newPath
|
439
|
+
|
440
|
+
if uiConfig.logoPath is not None:
|
441
|
+
|
442
|
+
fileName = uiConfig.logoPath.split('/')[-1]
|
443
|
+
|
444
|
+
dest = f"{revisitPath}/public/__revisit-widget/assets/{fileName}"
|
445
|
+
|
446
|
+
extracted_paths.append({
|
447
|
+
"src": uiConfig.logoPath,
|
448
|
+
"dest": dest
|
449
|
+
})
|
450
|
+
|
451
|
+
newPath = f"__revisit-widget/assets/{fileName}"
|
452
|
+
uiConfig.logoPath = newPath
|
453
|
+
|
454
|
+
# Copy all files
|
455
|
+
for item in extracted_paths:
|
456
|
+
_copy_file(item['src'], item['dest'])
|
457
|
+
|
458
|
+
w = _widget.Widget()
|
459
|
+
w.config = json.loads(study.__str__())
|
460
|
+
return w
|
461
|
+
|
462
|
+
|
369
463
|
# ------- PRIVATE FUNCTIONS ------------ #
|
370
464
|
|
371
465
|
def _validate_component(kwargs: dict):
|
@@ -496,7 +590,7 @@ def pretty_error(errors):
|
|
496
590
|
|
497
591
|
def _get_filtered_kwargs(class_type: Any, kwargs):
|
498
592
|
try:
|
499
|
-
possible_items = get_args(class_type.
|
593
|
+
possible_items = get_args(class_type.model_fields.get('root').annotation)
|
500
594
|
except AttributeError:
|
501
595
|
possible_items = [class_type]
|
502
596
|
|
@@ -529,3 +623,14 @@ def _extract_datum_value(text: str) -> str:
|
|
529
623
|
if match:
|
530
624
|
return match.group(1) # Return the captured part (i.e., 'thing')
|
531
625
|
return None # Return None if the pattern doesn't match
|
626
|
+
|
627
|
+
|
628
|
+
def _copy_file(src: str, dest: str):
|
629
|
+
# Check if file exists
|
630
|
+
if not os.path.exists(src):
|
631
|
+
raise RevisitError(message=f'File "{src}" not found.')
|
632
|
+
|
633
|
+
os.makedirs(os.path.dirname(dest), exist_ok=True)
|
634
|
+
|
635
|
+
print(f'Copying file from {src} to {dest}')
|
636
|
+
shutil.copyfile(src, dest)
|
revisit/widget.py
CHANGED
@@ -47,3 +47,7 @@ class Widget(anywidget.AnyWidget):
|
|
47
47
|
self.internalWidget.value += 1
|
48
48
|
# internalWidget.value += 1
|
49
49
|
# print("{name} changed from {old} to {new}".format(**change))
|
50
|
+
|
51
|
+
# def set(self, study: rvt._WrappedStudyConfig):
|
52
|
+
# self.config = json.loads(study.__str__())
|
53
|
+
# return self
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: revisit
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.8
|
4
4
|
Requires-Dist: anywidget
|
5
5
|
Requires-Dist: ipykernel>=6.29.5
|
6
6
|
Requires-Dist: pydantic>=2.10.5
|
@@ -58,3 +58,17 @@ yarn run dev
|
|
58
58
|
Open `example.ipynb` in JupyterLab, VS Code, or your favorite editor
|
59
59
|
to start developing. Changes made in `js/` will be reflected
|
60
60
|
in the notebook.
|
61
|
+
|
62
|
+
|
63
|
+
## CODE GEN
|
64
|
+
|
65
|
+
```bash
|
66
|
+
datamodel-codegen --input StudyConfigSchema.json --output models.py --custom-template-dir custom_templates --output-model-type pydantic_v2.BaseModel --additional-imports typing.TypedDict --input-file-type jsonschema --special-field-name-prefix we_are_going_to_replace_this && sed -i '' 's/we_are_going_to_replace_this_//g' src/revisit/models.py
|
67
|
+
```
|
68
|
+
|
69
|
+
## TESTS
|
70
|
+
|
71
|
+
```bash
|
72
|
+
cd revisit-py
|
73
|
+
python -m unittest tests.test_module_one
|
74
|
+
```
|
@@ -1,9 +1,9 @@
|
|
1
1
|
revisit/__init__.py,sha256=QCvYt8m9QwpjcK4dv6GlLMUDCzRXGy16cua1r2biNCg,255
|
2
2
|
revisit/models.py,sha256=c-Hsd6XqeIP-hybH6MUovHG65XXueRhaMEVJZW1ViX0,120701
|
3
|
-
revisit/revisit.py,sha256=
|
4
|
-
revisit/widget.py,sha256=
|
3
|
+
revisit/revisit.py,sha256=huYhGnzG5gL2KA3Lw0dIDCI8erm82uP6k5XDcoo_Q38,22683
|
4
|
+
revisit/widget.py,sha256=qx1xehXLLYlSdR44lDJ_nnb5czljsvGFBZNEV79G77I,1850
|
5
5
|
revisit/static/widget.css,sha256=TLu5F6k0CvowQtmApPswG-JZUXYszo7a10dVWKnZsIg,647
|
6
6
|
revisit/static/widget.js,sha256=MlZ2jHlh_ADsUKMC5nZaSAmW73-4y2B57NcS3E5Jh3Q,187153
|
7
|
-
revisit-0.0.
|
8
|
-
revisit-0.0.
|
9
|
-
revisit-0.0.
|
7
|
+
revisit-0.0.8.dist-info/METADATA,sha256=RShPLubx2i7A4ZKXmPy0uzGocBhkZHZmbpdDk4iobhQ,1712
|
8
|
+
revisit-0.0.8.dist-info/WHEEL,sha256=tkmg4JIqwd9H8mL30xA7crRmoStyCtGp0VWshokd1Jc,105
|
9
|
+
revisit-0.0.8.dist-info/RECORD,,
|
File without changes
|