revisit 0.0.6__tar.gz → 0.0.8__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: revisit
3
- Version: 0.0.6
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
+ ```
@@ -47,3 +47,17 @@ yarn run dev
47
47
  Open `example.ipynb` in JupyterLab, VS Code, or your favorite editor
48
48
  to start developing. Changes made in `js/` will be reflected
49
49
  in the notebook.
50
+
51
+
52
+ ## CODE GEN
53
+
54
+ ```bash
55
+ 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
56
+ ```
57
+
58
+ ## TESTS
59
+
60
+ ```bash
61
+ cd revisit-py
62
+ python -m unittest tests.test_module_one
63
+ ```
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "revisit"
7
- version = "0.0.6"
7
+ version = "0.0.8"
8
8
  dependencies = [
9
9
  "anywidget",
10
10
  "ipykernel>=6.29.5",
@@ -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
- for response in self.root.response:
84
- if response.root.id == id:
85
- response.set(**kwargs)
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, _WrappedComponentBlock) or isinstance(other, _WrappedComponent):
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: 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.__fields__.get('root').annotation)
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)
@@ -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
File without changes
File without changes
File without changes