modelflowib 2.84__tar.gz → 2.86__tar.gz

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 (53) hide show
  1. {modelflowib-2.84 → modelflowib-2.86}/PKG-INFO +3 -2
  2. {modelflowib-2.84 → modelflowib-2.86}/modelclass.py +19 -5
  3. {modelflowib-2.84 → modelflowib-2.86}/modelflowib.egg-info/PKG-INFO +3 -2
  4. {modelflowib-2.84 → modelflowib-2.86}/modelflowib.egg-info/requires.txt +2 -1
  5. {modelflowib-2.84 → modelflowib-2.86}/modelreport.py +15 -8
  6. {modelflowib-2.84 → modelflowib-2.86}/modelwidget.py +50 -13
  7. {modelflowib-2.84 → modelflowib-2.86}/pyproject.toml +3 -2
  8. {modelflowib-2.84 → modelflowib-2.86}/README.md +0 -0
  9. {modelflowib-2.84 → modelflowib-2.86}/license.md +0 -0
  10. {modelflowib-2.84 → modelflowib-2.86}/modelBLfunk.py +0 -0
  11. {modelflowib-2.84 → modelflowib-2.86}/model_Excel.py +0 -0
  12. {modelflowib-2.84 → modelflowib-2.86}/model_cvx.py +0 -0
  13. {modelflowib-2.84 → modelflowib-2.86}/model_dynare.py +0 -0
  14. {modelflowib-2.84 → modelflowib-2.86}/model_financial_stability.py +0 -0
  15. {modelflowib-2.84 → modelflowib-2.86}/model_latex.py +0 -0
  16. {modelflowib-2.84 → modelflowib-2.86}/model_latex_class.py +0 -0
  17. {modelflowib-2.84 → modelflowib-2.86}/model_parquet_mixin.py +0 -0
  18. {modelflowib-2.84 → modelflowib-2.86}/modelcausality.py +0 -0
  19. {modelflowib-2.84 → modelflowib-2.86}/modelconstruct.py +0 -0
  20. {modelflowib-2.84 → modelflowib-2.86}/modelconstruct_estimation.py +0 -0
  21. {modelflowib-2.84 → modelflowib-2.86}/modeldash.py +0 -0
  22. {modelflowib-2.84 → modelflowib-2.86}/modeldashboot.py +0 -0
  23. {modelflowib-2.84 → modelflowib-2.86}/modeldashsidebar.py +0 -0
  24. {modelflowib-2.84 → modelflowib-2.86}/modeldekom.py +0 -0
  25. {modelflowib-2.84 → modelflowib-2.86}/modeldiff.py +0 -0
  26. {modelflowib-2.84 → modelflowib-2.86}/modeldisplay.py +0 -0
  27. {modelflowib-2.84 → modelflowib-2.86}/modelestimation.py +0 -0
  28. {modelflowib-2.84 → modelflowib-2.86}/modelestimator_new.py +0 -0
  29. {modelflowib-2.84 → modelflowib-2.86}/modelflowib.egg-info/SOURCES.txt +0 -0
  30. {modelflowib-2.84 → modelflowib-2.86}/modelflowib.egg-info/dependency_links.txt +0 -0
  31. {modelflowib-2.84 → modelflowib-2.86}/modelflowib.egg-info/top_level.txt +0 -0
  32. {modelflowib-2.84 → modelflowib-2.86}/modelgrab.py +0 -0
  33. {modelflowib-2.84 → modelflowib-2.86}/modelgrabgdx.py +0 -0
  34. {modelflowib-2.84 → modelflowib-2.86}/modelgrabwf2.py +0 -0
  35. {modelflowib-2.84 → modelflowib-2.86}/modelhelp.py +0 -0
  36. {modelflowib-2.84 → modelflowib-2.86}/modelhtml.py +0 -0
  37. {modelflowib-2.84 → modelflowib-2.86}/modelinput_shiny.py +0 -0
  38. {modelflowib-2.84 → modelflowib-2.86}/modelinvert.py +0 -0
  39. {modelflowib-2.84 → modelflowib-2.86}/modeljupyter.py +0 -0
  40. {modelflowib-2.84 → modelflowib-2.86}/modeljupytermagic.py +0 -0
  41. {modelflowib-2.84 → modelflowib-2.86}/modelmacrograb.py +0 -0
  42. {modelflowib-2.84 → modelflowib-2.86}/modelmanipulation.py +0 -0
  43. {modelflowib-2.84 → modelflowib-2.86}/modelmf.py +0 -0
  44. {modelflowib-2.84 → modelflowib-2.86}/modelnet.py +0 -0
  45. {modelflowib-2.84 → modelflowib-2.86}/modelnewton.py +0 -0
  46. {modelflowib-2.84 → modelflowib-2.86}/modelnormalize.py +0 -0
  47. {modelflowib-2.84 → modelflowib-2.86}/modelpattern.py +0 -0
  48. {modelflowib-2.84 → modelflowib-2.86}/modelsolver_ng.py +0 -0
  49. {modelflowib-2.84 → modelflowib-2.86}/modeluserfunk.py +0 -0
  50. {modelflowib-2.84 → modelflowib-2.86}/modelvis.py +0 -0
  51. {modelflowib-2.84 → modelflowib-2.86}/modelwidget_core.py +0 -0
  52. {modelflowib-2.84 → modelflowib-2.86}/modelwidget_input.py +0 -0
  53. {modelflowib-2.84 → modelflowib-2.86}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modelflowib
3
- Version: 2.84
3
+ Version: 2.86
4
4
  Summary: A tool to solve and manage dynamic economic and financial models
5
5
  Author-email: Ib Hansen <Ib.Hansen.Iv@gmail.com>
6
6
  License-Expression: MIT
@@ -21,7 +21,6 @@ Requires-Dist: networkx
21
21
  Requires-Dist: tqdm
22
22
  Requires-Dist: scipy
23
23
  Requires-Dist: XlsxWriter
24
- Requires-Dist: pyarrow
25
24
  Requires-Dist: tabulate
26
25
  Requires-Dist: openpyxl
27
26
  Requires-Dist: xarray
@@ -41,7 +40,9 @@ Requires-Dist: dash; sys_platform != "emscripten"
41
40
  Requires-Dist: dash-bootstrap-components; sys_platform != "emscripten"
42
41
  Requires-Dist: dash-interactive-graphviz; sys_platform != "emscripten"
43
42
  Requires-Dist: plotly; sys_platform != "emscripten"
43
+ Requires-Dist: pyarrow; sys_platform != "emscripten"
44
44
  Requires-Dist: jupyter; sys_platform != "emscripten"
45
+ Requires-Dist: jupyterlab-myst; sys_platform != "emscripten"
45
46
  Provides-Extra: shiny
46
47
  Requires-Dist: shiny; extra == "shiny"
47
48
  Requires-Dist: shinywidgets; extra == "shiny"
@@ -2390,7 +2390,7 @@ class Model_help_Mixin():
2390
2390
  f'&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{blanks} <a href="{githubname}" target="_blank">{name}</a>'))
2391
2391
  else:
2392
2392
  display(HTML(
2393
- f'&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{blanks} <a href="{notebook}" target="_blank">{name}</a>'))
2393
+ f'&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{blanks} <a href="{notebook.as_posix()}" target="_blank">{name}</a>'))
2394
2394
 
2395
2395
 
2396
2396
 
@@ -5246,6 +5246,11 @@ class Graph_Draw_Mixin():
5246
5246
 
5247
5247
  class Display_Mixin():
5248
5248
 
5249
+ #: True: the result viewers (mpak['...'] and .rplot()) are shown as plain html tabs and
5250
+ #: collapsible sections instead of ipywidgets. They then also display where ipywidgets
5251
+ #: containers don't, like RISE slides. Set it for all models with model.plain_html = True
5252
+ plain_html = False
5253
+
5249
5254
  def vis(self, *args, **kwargs):
5250
5255
  ''' Visualize the data of this model instance
5251
5256
  if the user has another vis class she can place it in _vis, then that will be used'''
@@ -6454,7 +6459,7 @@ class Display_Mixin():
6454
6459
  title = Display_Mixin._notebook_title(notebook)
6455
6460
  rows.append(
6456
6461
  f'<tr><td style="text-align:left;padding:2px 24px 2px {indent+2}em;white-space:nowrap">'
6457
- f'<a href="{notebook}" target="_blank">{name}</a></td>'
6462
+ f'<a href="{notebook.as_posix()}" target="_blank">{name}</a></td>'
6458
6463
  f'<td style="text-align:left;padding:2px 12px">{title}</td></tr>')
6459
6464
 
6460
6465
  # try:
@@ -6514,7 +6519,7 @@ class Display_Mixin():
6514
6519
  title = Display_Mixin._notebook_title(fname) if ext == 'ipynb' else ''
6515
6520
  rows.append(
6516
6521
  f'<tr><td style="text-align:left;padding:2px 24px 2px 12px;white-space:nowrap">'
6517
- f'<a href="{fname}" target="_blank">{name}</a></td>'
6522
+ f'<a href="{fname.as_posix()}" target="_blank">{name}</a></td>'
6518
6523
  f'<td style="text-align:left;padding:2px 12px">{title}</td></tr>')
6519
6524
  if rows:
6520
6525
  display(HTML(
@@ -6843,11 +6848,20 @@ class Json_Mixin():
6843
6848
  base.index = base_dates
6844
6849
  return base, current_dates
6845
6850
 
6851
+ def any_case(p):
6852
+ '''p, or else a file in the same folder whose name only differs in case
6853
+ (Windows ignores case, Linux and the browser (JupyterLite) do not)'''
6854
+ if p.exists() or not p.parent.is_dir():
6855
+ return p
6856
+ return next((f for f in p.parent.iterdir() if f.name.lower() == p.name.lower()), p)
6857
+
6846
6858
  pinfile = Path(nname:=infile.replace('\\','/'))
6847
6859
  if not pinfile.suffix:
6848
- pinfile = pinfile.with_suffix(cls.data_suffix)
6849
- if not pinfile.exists() and (nodata := pinfile.with_suffix(cls.nodata_suffix)).exists():
6860
+ pinfile = any_case(pinfile.with_suffix(cls.data_suffix))
6861
+ if not pinfile.exists() and (nodata := any_case(pinfile.with_suffix(cls.nodata_suffix))).exists():
6850
6862
  pinfile = nodata
6863
+ else:
6864
+ pinfile = any_case(pinfile)
6851
6865
 
6852
6866
  def read_file(pinfile):
6853
6867
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modelflowib
3
- Version: 2.84
3
+ Version: 2.86
4
4
  Summary: A tool to solve and manage dynamic economic and financial models
5
5
  Author-email: Ib Hansen <Ib.Hansen.Iv@gmail.com>
6
6
  License-Expression: MIT
@@ -21,7 +21,6 @@ Requires-Dist: networkx
21
21
  Requires-Dist: tqdm
22
22
  Requires-Dist: scipy
23
23
  Requires-Dist: XlsxWriter
24
- Requires-Dist: pyarrow
25
24
  Requires-Dist: tabulate
26
25
  Requires-Dist: openpyxl
27
26
  Requires-Dist: xarray
@@ -41,7 +40,9 @@ Requires-Dist: dash; sys_platform != "emscripten"
41
40
  Requires-Dist: dash-bootstrap-components; sys_platform != "emscripten"
42
41
  Requires-Dist: dash-interactive-graphviz; sys_platform != "emscripten"
43
42
  Requires-Dist: plotly; sys_platform != "emscripten"
43
+ Requires-Dist: pyarrow; sys_platform != "emscripten"
44
44
  Requires-Dist: jupyter; sys_platform != "emscripten"
45
+ Requires-Dist: jupyterlab-myst; sys_platform != "emscripten"
45
46
  Provides-Extra: shiny
46
47
  Requires-Dist: shiny; extra == "shiny"
47
48
  Requires-Dist: shinywidgets; extra == "shiny"
@@ -7,7 +7,6 @@ networkx
7
7
  tqdm
8
8
  scipy
9
9
  XlsxWriter
10
- pyarrow
11
10
  tabulate
12
11
  openpyxl
13
12
  xarray
@@ -29,7 +28,9 @@ dash
29
28
  dash-bootstrap-components
30
29
  dash-interactive-graphviz
31
30
  plotly
31
+ pyarrow
32
32
  jupyter
33
+ jupyterlab-myst
33
34
 
34
35
  [shiny]
35
36
  shiny
@@ -1525,15 +1525,22 @@ class DisplayKeepFigDef(DisplayDef):
1525
1525
  return [self.out_html ]
1526
1526
 
1527
1527
 
1528
- @property
1529
- def out_html(self):
1528
+ @property
1529
+ def fig_tabwidget(self):
1530
1530
  figlist = {t: htmlwidget_fig(f) for t,f in self.figs.items() }
1531
- out = tabwidget(figlist,tab=False,selected_index=0)
1532
- return out.datawidget
1533
-
1534
-
1535
- # def _ipython_display_(self):
1536
- # display(self.out_html)
1531
+ return tabwidget(figlist,tab=False,selected_index=0)
1532
+
1533
+ @property
1534
+ def out_html(self):
1535
+ return self.fig_tabwidget.datawidget
1536
+
1537
+
1538
+ def _ipython_display_(self):
1539
+ # model.plain_html: the charts in plain html sections, which also display where ipywidgets containers don't (RISE)
1540
+ if getattr(self.mmodel, 'plain_html', False):
1541
+ display(HTML(self.fig_tabwidget.html))
1542
+ else:
1543
+ display(self.out_html)
1537
1544
 
1538
1545
  # display(self.out_html)
1539
1546
 
@@ -15,8 +15,9 @@ import ipywidgets as widgets
15
15
  # except:
16
16
  # ...
17
17
  # print('No ipysheet ')
18
- from IPython.display import display, clear_output,Latex, Markdown
18
+ from IPython.display import display, clear_output,Latex, Markdown, HTML
19
19
  from dataclasses import dataclass,field
20
+ import uuid
20
21
  import matplotlib.pylab as plt
21
22
 
22
23
  try:
@@ -41,8 +42,34 @@ class basewidget:
41
42
  ''' will update container widgets'''
42
43
  for w in self.datachildren:
43
44
  w.update_df(df,current_per)
44
-
45
-
45
+
46
+
47
+ def html_tabs(parts, tab=True, selected=0):
48
+ '''Plain html (no ipywidgets) version of a Tab or an Accordion, used when model.plain_html is True.
49
+
50
+ parts: {title: html string}. tab=True gives tabs made of hidden radio buttons, labels and css,
51
+ tab=False collapsible <details> sections. selected: the index shown first (None: all closed). '''
52
+ uid = 'mft' + uuid.uuid4().hex[:8] # unique, so tabs in other outputs are not affected
53
+ if not tab:
54
+ # the same name makes the sections exclusive: opening one closes the others
55
+ return ''.join(f'<details name="{uid}"{" open" if i == selected else ""}>'
56
+ f'<summary style="cursor:pointer;font-weight:bold">{title}</summary>{body}</details>'
57
+ for i, (title, body) in enumerate(parts.items()))
58
+ css = [f'#{uid} > input {{display:none}}',
59
+ f'#{uid} > label {{display:inline-block;padding:4px 12px;margin-right:2px;cursor:pointer;'
60
+ f'border:1px solid #bbb;border-bottom:none;border-radius:4px 4px 0 0;background:#eee}}',
61
+ f'#{uid} > div {{display:none;border-top:1px solid #bbb;padding-top:6px}}']
62
+ head, panels = '', ''
63
+ for i, (title, body) in enumerate(parts.items()):
64
+ rid = f'{uid}-{i}'
65
+ head += (f'<input type="radio" name="{uid}" id="{rid}"{" checked" if i == (selected or 0) else ""}>'
66
+ f'<label for="{rid}">{title}</label>')
67
+ panels += f'<div>{body}</div>'
68
+ css.append(f'#{rid}:checked + label {{background:#fff;font-weight:bold}}')
69
+ css.append(f'#{rid}:checked ~ div:nth-of-type({i + 1}) {{display:block}}')
70
+ return f'<style>{" ".join(css)}</style><div id="{uid}">{head}{panels}</div>'
71
+
72
+
46
73
  @dataclass
47
74
  class tabwidget:
48
75
  '''A widget to create tab or acordium contaners'''
@@ -62,8 +89,13 @@ class tabwidget:
62
89
 
63
90
  for i,key in enumerate(self.tabdefdict.keys()):
64
91
  self.datawidget.set_title(i,key)
65
-
66
-
92
+
93
+ @property
94
+ def html(self):
95
+ ''' the same container as plain html, see html_tabs '''
96
+ return html_tabs({key: child.html for key, child in zip(self.tabdefdict.keys(), self.datachildren)},
97
+ tab=self.tab, selected=self.selected_index)
98
+
67
99
  def update_df(self,df,current_per):
68
100
  ''' will update container widgets'''
69
101
  for w in self.datachildren:
@@ -514,6 +546,7 @@ table, th, td {
514
546
 
515
547
  self.whtml = widgets.HTML(image)
516
548
  self.datawidget=widgets.VBox([self.wexp,self.whtml]) if len(self.expname) else self.whtml
549
+ self.html = (f'<div>{self.expname}</div>' if len(self.expname) else '') + image
517
550
 
518
551
 
519
552
 
@@ -540,6 +573,7 @@ class htmlwidget_fig:
540
573
  image = fig_to_image(self.figs,format=self.format)
541
574
  self.whtml = widgets.HTML(image)
542
575
  self.datawidget=widgets.VBox([self.wexp,self.whtml]) if len(self.expname) else self.whtml
576
+ self.html = (f'<div>{self.expname}</div>' if len(self.expname) else '') + image
543
577
 
544
578
  @dataclass
545
579
  class htmlwidget_style:
@@ -561,7 +595,8 @@ table, th, td {
561
595
  }
562
596
  </style>
563
597
  """
564
- self.datawidget = widgets.HTML(f'{style_html}{self.styler.to_html()}' )
598
+ self.html = f'{style_html}{self.styler.to_html()}'
599
+ self.datawidget = widgets.HTML(self.html)
565
600
 
566
601
  def display(self):
567
602
  # Function to display the widget
@@ -580,9 +615,10 @@ class htmlwidget_label:
580
615
  ...
581
616
 
582
617
  self.wexp = widgets.Label(value = self.expname,layout={'width':'54%'})
583
-
584
-
618
+
619
+
585
620
  self.datawidget=self.wexp
621
+ self.html = f'<div>{self.expname}</div>'
586
622
 
587
623
  @dataclass
588
624
  class htmlwidget_text:
@@ -593,8 +629,9 @@ class htmlwidget_text:
593
629
 
594
630
  def __post_init__(self):
595
631
  # Initialize the label widget with the provided text
632
+ self.html = f"<p style='font-family:sans-serif;'>{self.text}</p>"
596
633
  self.datawidget = widgets.HTML(
597
- value=f"<p style='font-family:sans-serif;'>{self.text}</p>",
634
+ value=self.html,
598
635
  layout={'width': '90%'}
599
636
  )
600
637
 
@@ -684,10 +721,10 @@ class visshow:
684
721
  # print('exo inf created')
685
722
 
686
723
  this = tabwidget(tabnew,selected_index=0)
687
- # print('this created ')
688
-
689
-
690
- self.datawidget = this.datawidget
724
+ # print('this created ')
725
+
726
+ # model.plain_html: plain html tabs, which also display where ipywidgets containers don't (RISE)
727
+ self.datawidget = HTML(this.html) if getattr(self.mmodel, 'plain_html', False) else this.datawidget
691
728
  if self.show_on:
692
729
  ...
693
730
  display(self.datawidget)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "modelflowib" # PyPI distribution name
7
- version = "2.84" # OVERWRITTEN at build time from MF_VERSION
7
+ version = "2.86" # OVERWRITTEN at build time from MF_VERSION
8
8
  # (set_pyproject_version.py / make_pip.py -v)
9
9
  description = "A tool to solve and manage dynamic economic and financial models"
10
10
  readme = "README.md"
@@ -36,7 +36,6 @@ dependencies = [
36
36
  "tqdm",
37
37
  "scipy",
38
38
  "XlsxWriter",
39
- "pyarrow",
40
39
  "tabulate",
41
40
  "openpyxl",
42
41
  "xarray",
@@ -57,7 +56,9 @@ dependencies = [
57
56
  "dash-bootstrap-components; sys_platform != 'emscripten'",
58
57
  "dash-interactive-graphviz; sys_platform != 'emscripten'",
59
58
  "plotly; sys_platform != 'emscripten'", # modeldashsidebar
59
+ "pyarrow; sys_platform != 'emscripten'", # only .pcimz (large=True) dump/load; not in every Pyodide (0.27 lacks it)
60
60
  "jupyter; sys_platform != 'emscripten'", # JupyterLite is the notebook there
61
+ "jupyterlab-myst; sys_platform != 'emscripten'", # MyST markdown (directives, mermaid) in notebook cells; a front-end extension, in JupyterLite it comes from the site build
61
62
  ]
62
63
 
63
64
  [project.optional-dependencies]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes