ipyvasp 0.9.3__py2.py3-none-any.whl → 0.9.5__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.
ipyvasp/_version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.9.3"
1
+ __version__ = "0.9.5"
@@ -1019,7 +1019,7 @@ def iplot2widget(fig, fig_widget=None, template=None):
1019
1019
  elif not isinstance(fig_widget, go.FigureWidget):
1020
1020
  raise ValueError("fig_widget must be FigureWidget")
1021
1021
  else:
1022
- scene = fig_widget.layout.scene # keep scene from widget
1022
+ scene = fig_widget.layout.scene if fig_widget.data else fig.layout.scene# keep scene from widget, but if looks a new fig, keep from previous
1023
1023
 
1024
1024
  fig_widget.data = [] # Clear previous data
1025
1025
  if template is not None:
ipyvasp/widgets.py CHANGED
@@ -106,12 +106,14 @@ class Files:
106
106
  Parameters
107
107
  ----------
108
108
  path_or_files : str, current directory by default or list of files or an instance of Files.
109
- glob : str, glob pattern, '*' by default. Not used if files supplied above.
109
+ glob : str, glob pattern, '*' by default. '**' is used for recursive glob. Not used if files supplied above.
110
110
  exclude : str, regular expression pattern to exclude files.
111
111
  files_only : bool, if True, returns only files.
112
112
  dirs_only : bool, if True, returns only directories.
113
113
 
114
114
  Use methods on return such as `summarize`, `with_name`, `filtered`, `interact` and others.
115
+
116
+ >>> Files(root_1, glob_1,...).add(root_2, glob_2,...) # Fully flexible to chain
115
117
  """
116
118
  def __init__(self, path_or_files = '.', glob = '*', exclude = None,files_only = False, dirs_only=False):
117
119
  if isinstance(path_or_files, Files):
@@ -123,8 +125,7 @@ class Files:
123
125
 
124
126
  files = []
125
127
  if isinstance(path_or_files,(str, Path)):
126
- path = Path(path_or_files)
127
- files = [p for p in path.glob(glob)]
128
+ files = Path(path_or_files).glob(glob)
128
129
  else:
129
130
  others = []
130
131
  for item in path_or_files:
@@ -142,23 +143,34 @@ class Files:
142
143
  print(f"Skipping paths that do not exist: {list(set(others))}")
143
144
 
144
145
  if exclude:
145
- files = [p for p in files if not re.search(exclude, str(p))]
146
+ files = (p for p in files if not re.search(exclude, str(p)))
146
147
  if files_only:
147
- files = [p for p in files if p.is_file()]
148
+ files = (p for p in files if p.is_file())
148
149
  if dirs_only:
149
- files = [p for p in files if p.is_dir()]
150
+ files = (p for p in files if p.is_dir())
150
151
 
151
152
  self._files = tuple(sorted(files))
152
153
 
154
+ def __str__(self):
155
+ return '\n'.join(str(f) for f in self._files)
156
+
153
157
  def __repr__(self):
154
158
  if not self: return "Files()"
155
- return "Files(\n" + ',\n'.join(f' {f!r}' for f in self._files) + "\n)"
159
+ show = ',\n'.join(f' {f!r}' for f in self._files)
160
+ return f"Files(\n{show}\n) {len(self._files)} items"
156
161
 
157
162
  def __getitem__(self, index): return self._files[index]
158
163
  def __iter__(self): return self._files.__iter__()
159
164
  def __len__(self): return len(self._files)
160
165
  def __bool__(self): return bool(self._files)
161
166
 
167
+ def __add__(self, other):
168
+ raise NotImplementedError("Use self.add method instead!")
169
+
170
+ def map(self,func):
171
+ "Map files to a function!"
172
+ return map(func, self._files)
173
+
162
174
  def with_name(self, name):
163
175
  "Change name of all files. Only keeps existing files."
164
176
  return self.__class__([f.with_name(name) for f in self._files])
@@ -195,28 +207,52 @@ class Files:
195
207
 
196
208
  return self.with_name('POSCAR').summarize(info, tags=tags)
197
209
 
198
- def update(self, path_or_files, glob = '*',**kwargs):
199
- "Update files inplace with similar parameters as initialization. Useful for widgets such as BandsWidget to preserve their state while files swapping."
200
- self._files = self.__class__(path_or_files, glob = glob, **kwargs)
210
+ def update(self, path_or_files, glob = '*', cleanup = True, exclude=None,**kwargs):
211
+ """Update files inplace with similar parameters as initialization. If `cleanup=False`, older files are kept too.
212
+ Useful for widgets such as BandsWidget to preserve their state while using `widget.files.update`."""
213
+ old = () if cleanup else self._files
214
+ self._files = self._unique(old, self.__class__(path_or_files, glob = glob, exclude=exclude,**kwargs)._files)
215
+
201
216
  if (dd := getattr(self, '_dd', None)): # update dropdown
202
217
  old = dd.value
203
218
  dd.options = self._files
204
219
  if old in dd.options:
205
220
  dd.value = old
206
221
 
207
- def interactive(self, func,
208
- other_widgets=None,
209
- other_controls=None,
222
+ def add(self, path_or_files, glob = '*', exclude=None, **kwargs):
223
+ """Add more files or with a diffrent glob on top of exitsing files. Returns same instance.
224
+ Useful to add multiple globbed files into a single chained call.
225
+
226
+ >>> Files(root_1, glob_1,...).add(root_2, glob_2,...) # Fully flexible
227
+ """
228
+ self._files = self._unique(self._files, self.__class__(path_or_files, glob = glob, exclude=exclude,**kwargs)._files)
229
+ return self
230
+
231
+ def _unique(self, *files_tuples):
232
+ return tuple(np.unique(np.hstack(files_tuples)))
233
+
234
+ def interactive(self, func, *args,
235
+ free_widgets=None,
210
236
  options={"manual": False},
211
237
  height="400px",
238
+ panel_size = 25,
212
239
  **kwargs):
213
240
  """
214
- Interact with a function that takes selected Path as first argument. Returns a widget that saves attributes of the function call such as .f, .args, .kwargs.
241
+ Interact with `func(path, *args, <free_widgets,optional>, **kwargs)` that takes selected Path as first argument. Returns a widget that saves attributes of the function call such as .f, .args, .kwargs.
242
+ `args` are widgets to be modified by func, such as plotly's FigureWidget.
243
+ Note that `free_widgets` can also be passed to function but does not run function when changed.
244
+
215
245
  See docs of self.interact for more details on the parameters. kwargs are passed to ipywidgets.interactive to create controls.
216
246
 
247
+ >>> import plotly.graph_objects as go
248
+ >>> import ipyvasp as ipv
249
+ >>> fs = ipv.Files('.','**/POSCAR')
250
+ >>> def plot(path, fig, bl,plot_cell,eqv_sites):
251
+ >>> ipv.iplot2widget(ipv.POSCAR(path).iplot_lattice(
252
+ >>> bond_length=bl,plot_cell=plot_cell,eqv_sites=eqv_sites
253
+ >>> ),fig_widget=fig) # it keeps updating same view
254
+ >>> out = fs.interactive(plot, go.FigureWidget(),bl=(0,6,2),plot_cell=True, eqv_sites=True)
217
255
 
218
- >>> fls = Files()
219
- >>> out = fls.interactive(lambda path: print(path.read_text())) # prints contents of selected file on output widget
220
256
  >>> out.f # function
221
257
  >>> out.args # arguments
222
258
  >>> out.kwargs # keyword arguments
@@ -228,13 +264,16 @@ class Files:
228
264
  info = ipw.HTML().add_class("fprogess")
229
265
  dd = Dropdown(description='File', options=self._files)
230
266
 
231
- def interact_func(fname, **kwargs):
267
+ def interact_func(fname, **kws):
232
268
  if fname: # This would be None if no file is selected
233
269
  info.value = _progress_svg
234
270
  try:
235
271
  start = time()
236
- print(f"Running {func.__name__}({fname!r}, {kwargs})")
237
- func(Path(fname).absolute(), **kwargs) # Have Path object absolue if user changes directory
272
+ if 'free_widgets' in func.__code__.co_varnames:
273
+ kws['free_widgets'] = free_widgets # user allowed to pass this
274
+ names = ', '.join(func.__code__.co_varnames)
275
+ print(f"Running {func.__name__}({names})")
276
+ func(Path(fname).absolute(), *args, **kws) # Have Path object absolue if user changes directory
238
277
  print(f"Finished in {time() - start:.3f} seconds.")
239
278
  finally:
240
279
  info.value = ""
@@ -253,38 +292,45 @@ class Files:
253
292
  ) # make output scrollable and avoid overflow
254
293
 
255
294
  others = out.children[1:-1] # exclude files_dd and Output widget
256
- _style = """<style>
257
- .files-interact {
295
+ if not isinstance(panel_size,int):
296
+ raise TypeError('panel_size should be integer in units of em')
297
+
298
+ _style = f"""<style>
299
+ .files-interact {{
258
300
  --jp-widgets-inline-label-width: 4em;
259
- --jp-widgets-inline-width: 18em;
301
+ --jp-widgets-inline-width: {panel_size-2}em;
260
302
  --jp-widgets-inline-width-short: 9em;
261
- }
262
- .files-interact {max-height:90vh;width:100%;}
263
- .files-interact > div {overflow:auto;max-height:100%;padding:8px;}
264
- .files-interact > div:first-child {width:20em}
265
- .files-interact > div:last-child {width:calc(100% - 20em)}
266
- .files-interact .fprogess {position:absolute !important; left:50%; top:50%; transform:translate(-50%,-50%); z-index:1}
303
+ }}
304
+ .files-interact {{max-height:{height};width:100%;}}
305
+ .files-interact > div {{overflow:auto;max-height:100%;padding:8px;}}
306
+ .files-interact > div:first-child {{width:{panel_size}em}}
307
+ .files-interact > div:last-child {{width:calc(100% - {panel_size}em)}}
308
+ .files-interact .fprogess {{position:absolute !important; left:50%; top:50%; transform:translate(-50%,-50%); z-index:1}}
267
309
  </style>"""
268
310
  if others:
269
311
  others = [ipw.HTML(f"<hr/>{_style}"), *others]
270
312
  else:
271
313
  others = [ipw.HTML(_style)]
272
314
 
273
- if other_controls and not isinstance(other_controls, (list, tuple)):
274
- raise TypeError("other_controls must be a list or tuple of widgets.")
275
-
276
- if other_widgets and not isinstance(other_widgets, (list, tuple)):
277
- raise TypeError("other_widgets must be a list or tuple of widgets.")
278
-
279
- if other_widgets:
315
+ if free_widgets and not isinstance(free_widgets, (list, tuple)):
316
+ raise TypeError("free_widgets must be a list or tuple of widgets.")
317
+
318
+ for w in args:
319
+ if not isinstance(w,ipw.DOMWidget):
320
+ raise TypeError(f'args can only contain a DOMWidget instance, got {type(w)}')
321
+
322
+ if args:
280
323
  output.layout.max_height = "200px"
324
+ output.layout.min_height = "8em" # fisrt fix
281
325
  out_collapser = Checkbox(description="Hide output widget", value=False)
282
326
 
283
327
  def toggle_output(change):
284
328
  if out_collapser.value:
285
329
  output.layout.height = "0px" # dont use display = 'none' as it will clear widgets and wont show again
330
+ output.layout.min_height = "0px"
286
331
  else:
287
332
  output.layout.height = "auto"
333
+ output.layout.min_height = "8em"
288
334
 
289
335
  out_collapser.observe(toggle_output, "value")
290
336
  others.append(out_collapser)
@@ -293,20 +339,14 @@ class Files:
293
339
  others = [
294
340
  *others,
295
341
  ipw.HTML(f"<hr/>"),
296
- *(other_controls or []),
342
+ *(free_widgets or []),
297
343
  ] # add hr to separate other controls
298
344
 
299
345
  out.children = [
300
- HBox(
301
- [ # reset children to include new widgets
302
- VBox(
303
- children=[dd, VBox(others)]
304
- ), # other widgets in box to make scrollable independent file selection
305
- VBox(
306
- children=[Box([output]), *(other_widgets or []), info]
307
- ), # output in box to make scrollable,
308
- ],
309
- layout=Layout(height=height, max_height=height),
346
+ HBox([ # reset children to include new widgets
347
+ VBox([dd, VBox(others)]), # other widgets in box to make scrollable independent file selection
348
+ VBox([Box([output]), *args, info]), # output in box to make scrollable,
349
+ ],layout=Layout(height=height, max_height=height),
310
350
  ).add_class("files-interact")
311
351
  ] # important for every widget separately
312
352
  return out
@@ -317,61 +357,64 @@ class Files:
317
357
  box.children = box._interact.children
318
358
  box._files._dd = box._interact._dd
319
359
 
320
- def interact(self,
321
- other_widgets=None,
322
- other_controls=None,
360
+ def interact(self, *args,
361
+ free_widgets=None,
323
362
  options={"manual": False},
324
363
  height="400px",
364
+ panel_size=25,
325
365
  **kwargs,
326
366
  ):
327
- """Interact with a function that takes a selected Path as first argument.
367
+ """Interact with a `func(path, *args, <free_widgets,optional>, **kwargs)`. `path` is passed from selected File.
328
368
  A CSS class 'files-interact' is added to the final widget to let you style it.
329
369
 
330
370
  Parameters
331
371
  ----------
332
- other_widgets : list/tuple
372
+ args :
333
373
  Any displayable widget can be passed. These are placed below the output widget of interact.
334
- For example you can add plotly's FigureWidget that updates based on the selection, but is not part of the function, so it is displayed only once.
335
- other_controls : list/tuple
336
- Default is None. If not None, these are assumed to be ipywidgets and are placed below the widgets created by kwargs. These are not passed to the decorated function.
374
+ For example you can add plotly's FigureWidget that updates based on the selection, these are passed to function after path.
375
+ free_widgets : list/tuple
376
+ Default is None. If not None, these are assumed to be ipywidgets and are placed below the widgets created by kwargs.
377
+ These can be passed to the decorated function if added as arguemnt there like `func(..., free_widgets)`, but don't trigger execution.
337
378
  options : dict
338
- Default is {'manua':False}. If True, the decorated function is not called automatically, and you have to call it manually on button press. You can pass button name as 'manual_name' in options.
379
+ Default is {'manual':False}. If True, the decorated function is not called automatically, and you have to call it manually on button press. You can pass button name as 'manual_name' in options.
339
380
  height : str
340
381
  Default is '90vh'. height of the final widget. This is important to avoid very long widgets.
382
+ panel_size: int
383
+ Side panel size in units of em.
341
384
 
342
385
  kwargs are passed to ipywidgets.interactive and decorated function. Resulting widgets are placed below the file selection widget.
343
- `other_widgets` can be controlled by `other_controls` externally. For example, you can add a button to update a plotly's FigureWidget.
386
+ Widgets in `args` can be controlled by `free_widgets` externally if defined gloablly or inside function if you pass `free_widgets` as argument like `func(..., free_widgets)`.
344
387
 
345
388
  The decorated function can be called later separately as well, and has .args and .kwargs attributes to access the latest arguments
346
389
  and .result method to access latest. For a function `f`, `f.result` is same as `f(*f.args, **f.kwargs)`.
347
390
 
348
-
349
- >>> fls = Files()
350
- >>> @fls.interact(x = False)
351
- >>> def f(path,x):
352
- >>> print('path:',path)
353
- >>> print('Path Type: ', type(path))
354
- >>> print('x: ',x)
391
+ >>> import plotly.graph_objects as go
392
+ >>> import ipyvasp as ipv
393
+ >>> fs = ipv.Files('.','**/POSCAR')
394
+ >>> @fs.interact(go.FigureWidget(),bl=(0,6,2),plot_cell=True, eqv_sites=True)
395
+ >>> def plot(path, fig, bl,plot_cell,eqv_sites):
396
+ >>> ipv.iplot2widget(ipv.POSCAR(path).iplot_lattice(
397
+ >>> bond_length=bl,plot_cell=plot_cell,eqv_sites=eqv_sites
398
+ >>> ),fig_widget=fig) # it keeps updating same view
355
399
 
356
400
  .. note::
357
401
  Use self.interactive to get a widget that stores the argements and can be called later in a notebook cell.
358
402
  """
359
403
 
360
404
  def inner(func):
361
- display(self.interactive(func,
362
- other_widgets=other_widgets,
363
- other_controls=other_controls,
405
+ display(self.interactive(func, *args,
406
+ free_widgets=free_widgets,
364
407
  options=options,
365
408
  height=height,
409
+ panel_size=panel_size,
366
410
  **kwargs)
367
411
  )
368
412
  return func
369
413
  return inner
370
414
 
371
-
372
415
  def kpath_widget(self, height='400px'):
373
416
  "Get KpathWidget instance with these files."
374
- return KpathWidget(files = self._files, height = height)
417
+ return KpathWidget(files = self.with_name('POSCAR'), height = height)
375
418
 
376
419
  def bands_widget(self, height='450px'):
377
420
  "Get BandsWidget instance with these files."
@@ -596,10 +639,8 @@ class BandsWidget(VBox):
596
639
  self._select_dict = {} # store selection data
597
640
  self._kwargs = {}
598
641
 
599
- Files(files)._attributed_interactive(self,
600
- self._load_data,
601
- other_widgets=[self._fig],
602
- other_controls=[
642
+ Files(files)._attributed_interactive(self, self._load_data, self._fig,
643
+ free_widgets=[
603
644
  self._tsd,
604
645
  self._brange,
605
646
  self._ktcicks,
@@ -626,7 +667,8 @@ class BandsWidget(VBox):
626
667
  "Use slef.files.update(...) to keep state of widget preserved."
627
668
  return self._files
628
669
 
629
- def _load_data(self, path): # Automatically redirectes to output widget
670
+ def _load_data(self, path, fig): # Automatically redirectes to output widget
671
+ if not hasattr(self, '_interact'): return # First time not availablebu
630
672
  self._interact.output_widget.clear_output(wait=True) # Why need again?
631
673
  with self._interact.output_widget:
632
674
  self._bands = (
@@ -684,6 +726,7 @@ class BandsWidget(VBox):
684
726
  return self._select_dict.get("data", None)
685
727
 
686
728
  def _update_graph(self, btn):
729
+ if not hasattr(self, '_interact'): return # First time not available
687
730
  self._interact.output_widget.clear_output(wait=True) # Why need again?
688
731
  with self._interact.output_widget:
689
732
  hsk = [
@@ -815,7 +858,7 @@ class KpathWidget(VBox):
815
858
  self._clicktime = None
816
859
  self._kpoints = {}
817
860
 
818
- other_controls = [
861
+ free_widgets = [
819
862
  HBox([self._add, self._del, self._tsb], layout=Layout(min_height="24px")),
820
863
  ipw.HTML(
821
864
  "<style>.KpathWidget .widget-select-multiple { min-height: 180px; }\n .widget-select-multiple > select {height: 100%;}</style>"
@@ -826,7 +869,7 @@ class KpathWidget(VBox):
826
869
  ]
827
870
 
828
871
  Files(files)._attributed_interactive(self,
829
- self._update_fig, [self._fig], other_controls, height=height
872
+ self._update_fig, self._fig, free_widgets=free_widgets, height=height
830
873
  )
831
874
 
832
875
  self._tsb.on_click(self._update_theme)
@@ -850,7 +893,8 @@ class KpathWidget(VBox):
850
893
  "POSCAR class associated to current selection."
851
894
  return self._poscar
852
895
 
853
- def _update_fig(self, path):
896
+ def _update_fig(self, path, fig):
897
+ if not hasattr(self, '_interact'): return # First time not available
854
898
  from .lattice import POSCAR # to avoid circular import
855
899
 
856
900
  with self._interact.output_widget:
@@ -859,10 +903,10 @@ class KpathWidget(VBox):
859
903
  )
860
904
  self._poscar = POSCAR(path)
861
905
  ptk.iplot2widget(
862
- self._poscar.iplot_bz(fill=False, color="red"), self._fig, template
906
+ self._poscar.iplot_bz(fill=False, color="red"), fig, template
863
907
  )
864
- with self._fig.batch_animate():
865
- self._fig.add_trace(
908
+ with fig.batch_animate():
909
+ fig.add_trace(
866
910
  go.Scatter3d(
867
911
  x=[],
868
912
  y=[],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ipyvasp
3
- Version: 0.9.3
3
+ Version: 0.9.5
4
4
  Summary: A processing tool for VASP DFT input/output processing in Jupyter Notebook.
5
5
  Home-page: https://github.com/massgh/ipyvasp
6
6
  Author: Abdul Saboor
@@ -2,7 +2,7 @@ ipyvasp/__init__.py,sha256=rlorju9arMtHw1QRYPljday-PyZWJdSCxg4lw3g6t0Q,1409
2
2
  ipyvasp/__main__.py,sha256=eJV1TZSiT8mC_VqAeksNnBI2I8mKMiPkEIlwikbtOjI,216
3
3
  ipyvasp/_enplots.py,sha256=D38paN8zqZgluNAwmCwcocd7-_h_T0HTGolI1eBkDes,37484
4
4
  ipyvasp/_lattice.py,sha256=GxG0C4lwVGvBYIy3jwR1kahWR7L6kJlqjIiQGgESjcM,104135
5
- ipyvasp/_version.py,sha256=5uBZ3sUaocnyIWuJeW9M94Z77vA1kKmwKxiblrnbKlc,23
5
+ ipyvasp/_version.py,sha256=UvB3IZAWAs7vV6H9dpZvZPryrSNIyF5_bowVS4_YGFA,23
6
6
  ipyvasp/bsdos.py,sha256=1rG68S-dLEYveIWGK7r8CRa7Qqlqno0l1ncfo2ocihk,30424
7
7
  ipyvasp/cli.py,sha256=aWFEVhNmnW8eSOp5uh95JaDwLQ9K9nlCQcbnOSuhWgw,6844
8
8
  ipyvasp/evals_dataframe.py,sha256=-sqxK7LPV6sYDO_XXmZ80FznOaXTkVdbqJKKvTUtMak,20637
@@ -11,15 +11,15 @@ ipyvasp/misc.py,sha256=SZJ_ePUR2-HEKYTEpDHVRVE7zpIQVTCjiuw0BCC9UTU,2349
11
11
  ipyvasp/potential.py,sha256=tzA73c5lkp6ahLSJchMrU043-QWaOV0nIOUA7VMmfKQ,11408
12
12
  ipyvasp/surface.py,sha256=MjE5oB0wW6Pca_C-xu8rN6OMH7lUEeNPNyM7Kz_Im-8,23766
13
13
  ipyvasp/utils.py,sha256=rVyD5SkO_Y7ok5W-fJeQys9X8pLLbDK7VOgbAbcE4WU,14227
14
- ipyvasp/widgets.py,sha256=mP1tqYO-tPk4Xq_fgkGPGN2AfRf9V-al3Yl7vzKp5lU,43758
14
+ ipyvasp/widgets.py,sha256=hwCviQn5NmxFz15DTS2nKKJ0kdBq8taGude46KNDOtU,46605
15
15
  ipyvasp/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  ipyvasp/core/parser.py,sha256=C3CaZsJbPME_ttYlYy4DXeOdL7dnkXs-cHRwFZL6bio,38058
17
- ipyvasp/core/plot_toolkit.py,sha256=8t5svyWbOm-PS7ZvIptnK6F46kp6uwoGNdohPv5dQKA,35962
17
+ ipyvasp/core/plot_toolkit.py,sha256=3RoPsND5gPssBSfS5H4TjoZ2Qz7B97vpxeKadc2cRRs,36046
18
18
  ipyvasp/core/serializer.py,sha256=XpqnfVGsUXiN2CuVRPyqsSVouxRBO-UH6AnsHnPYvZY,36729
19
19
  ipyvasp/core/spatial_toolkit.py,sha256=8DBYTiBFWJ7OBKuvOPw7UoEVCyNjJhSW0OcudjYZvAw,14748
20
- ipyvasp-0.9.3.dist-info/LICENSE,sha256=F3SO5RiAZOMfmMGf1KOuk2g_c4ObvuBJhd9iBLDgXoQ,1263
21
- ipyvasp-0.9.3.dist-info/METADATA,sha256=v2jvMQ--zKh-b0GAF5XywZDMKJi8x3hUAMMvKGdfiD0,2420
22
- ipyvasp-0.9.3.dist-info/WHEEL,sha256=iYlv5fX357PQyRT2o6tw1bN-YcKFFHKqB_LwHO5wP-g,110
23
- ipyvasp-0.9.3.dist-info/entry_points.txt,sha256=C7m0Sjmr14wFjflCkWXLzr5N6-cQj8uJC9n82mUtzt8,44
24
- ipyvasp-0.9.3.dist-info/top_level.txt,sha256=ftziWlMWu_1VpDP1sRTFrkfBnWxAi393HYDVu4wRhUk,8
25
- ipyvasp-0.9.3.dist-info/RECORD,,
20
+ ipyvasp-0.9.5.dist-info/LICENSE,sha256=F3SO5RiAZOMfmMGf1KOuk2g_c4ObvuBJhd9iBLDgXoQ,1263
21
+ ipyvasp-0.9.5.dist-info/METADATA,sha256=Vfq6b9vA2i5LjHBcUTb8KkXkkCK3jldhXPNUm27MvsQ,2420
22
+ ipyvasp-0.9.5.dist-info/WHEEL,sha256=iYlv5fX357PQyRT2o6tw1bN-YcKFFHKqB_LwHO5wP-g,110
23
+ ipyvasp-0.9.5.dist-info/entry_points.txt,sha256=C7m0Sjmr14wFjflCkWXLzr5N6-cQj8uJC9n82mUtzt8,44
24
+ ipyvasp-0.9.5.dist-info/top_level.txt,sha256=ftziWlMWu_1VpDP1sRTFrkfBnWxAi393HYDVu4wRhUk,8
25
+ ipyvasp-0.9.5.dist-info/RECORD,,