nxswriter 3.11.1__py3-none-any.whl → 3.14.0__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.
nxswriter/EAttribute.py CHANGED
@@ -57,6 +57,24 @@ class EAttribute(FElement):
57
57
  #: (:obj:`str`) trigger for asynchronous writting
58
58
  self.trigger = None
59
59
 
60
+ def setRank(self, rank):
61
+ """ sets dimension rank
62
+
63
+ :param index: dimension rank
64
+ :type index: :obj:`src`
65
+ """
66
+ self.rank = rank
67
+
68
+ def setLength(self, index, value):
69
+ """ sets lengths dict element
70
+
71
+ :param index: length index
72
+ :type index: :obj:`int`
73
+ :param value: length value
74
+ :type value: :obj:`int` or :obj:`str`
75
+ """
76
+ self.lengths[index] = value
77
+
60
78
  def store(self, xml=None, globalJSON=None):
61
79
  """ stores the tag content
62
80
 
nxswriter/EField.py CHANGED
@@ -81,8 +81,6 @@ class EField(FElementWithAttr):
81
81
  self.shuffle = True
82
82
  #: (:obj:`bool`) grew flag
83
83
  self.__grew = True
84
- #: (:obj:`str`) data format
85
- self.__format = ''
86
84
 
87
85
  def __isgrowing(self):
88
86
  """ checks if it is growing in extra dimension
@@ -117,6 +115,24 @@ class EField(FElementWithAttr):
117
115
 
118
116
  raise XMLSettingSyntaxError("Field without a name")
119
117
 
118
+ def setRank(self, rank):
119
+ """ sets dimension rank
120
+
121
+ :param index: dimension rank
122
+ :type index: :obj:`src`
123
+ """
124
+ self.rank = rank
125
+
126
+ def setLength(self, index, value):
127
+ """ sets lengths dict element
128
+
129
+ :param index: length index
130
+ :type index: :obj:`int`
131
+ :param value: length value
132
+ :type value: :obj:`int` or :obj:`str`
133
+ """
134
+ self.lengths[index] = value
135
+
120
136
  def __getShape(self):
121
137
  """ provides shape
122
138
 
@@ -0,0 +1,718 @@
1
+ #!/usr/bin/env python
2
+ # This file is part of nexdatas - Tango Server for NeXus data writer
3
+ #
4
+ # Copyright (C) 2012-2017 DESY, Jan Kotanski <jkotan@mail.desy.de>
5
+ #
6
+ # nexdatas is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # nexdatas is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with nexdatas. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+
20
+ """ Definitions of field tag evaluation classes """
21
+
22
+ import sys
23
+
24
+ # import numpy
25
+ import json
26
+
27
+ from .DataHolder import DataHolder
28
+ from .Element import Element
29
+ from .FElement import FElementWithAttr
30
+ from .Types import NTP
31
+ from .Errors import (XMLSettingSyntaxError)
32
+
33
+ from nxstools import filewriter as FileWriter
34
+
35
+
36
+ class EVirtualSourceView(Element):
37
+
38
+ """ virtual source view tag element
39
+ """
40
+
41
+ def __init__(self, attrs, last, streams=None):
42
+ """ constructor
43
+
44
+ :param attrs: dictionary of the tag attributes
45
+ :type attrs: :obj:`dict` <:obj:`str`, :obj:`str`>
46
+ :param last: the last element from the stack
47
+ :type last: :class:`nxswriter.Element.Element`
48
+ :param streams: tango-like steamset class
49
+ :type streams: :class:`StreamSet` or :class:`tango.LatestDeviceImpl`
50
+ """
51
+ Element.__init__(self, "sourceview", attrs, last, streams=streams)
52
+ #: (:obj:`list` <:obj:`str`>) tag content
53
+ self.content = []
54
+
55
+ def setRank(self, rank):
56
+ """ sets dimension rank
57
+
58
+ :param index: dimension rank
59
+ :type index: :obj:`src`
60
+ """
61
+ self.last.setSourceRank(rank)
62
+
63
+ def setLength(self, index, value):
64
+ """ sets lengths dict element
65
+
66
+ :param index: length index
67
+ :type index: :obj:`int`
68
+ :param value: length value
69
+ :type value: :obj:`int` or :obj:`str`
70
+ """
71
+ self.last.setSourceLength(index, value)
72
+
73
+ def setSelection(self, index, value):
74
+ """ sets selection dict element
75
+
76
+ :param index: selection index
77
+ :type index: :obj:`int`
78
+ :param value: selection value
79
+ :type value: :obj:`int` or :obj:`str`
80
+ """
81
+ self.last.setSourceSelection(index, value)
82
+
83
+
84
+ class EVirtualDataMap(Element):
85
+
86
+ """ layout map tag element
87
+ """
88
+
89
+ def __init__(self, attrs, last, streams=None):
90
+ """ constructor
91
+
92
+ :param attrs: dictionary of the tag attributes
93
+ :type attrs: :obj:`dict` <:obj:`str`, :obj:`str`>
94
+ :param last: the last element from the stack
95
+ :type last: :class:`nxswriter.Element.Element`
96
+ :param streams: tango-like steamset class
97
+ :type streams: :class:`StreamSet` or :class:`tango.LatestDeviceImpl`
98
+ """
99
+ Element.__init__(self, "map", attrs, last, streams=streams)
100
+ #: (:obj:`str`) rank of the field
101
+ self.rank = "0"
102
+ #: (:obj:`str`) rank of the source field view
103
+ self.srcrank = "0"
104
+ #: (:obj:`dict` <:obj:`str`, :obj:`str`>) \
105
+ #: shape of the field, i.e. {index: length}
106
+ self.lengths = {}
107
+ #: (:obj:`dict` <:obj:`str`, :obj:`str`>) \
108
+ #: selection of the field, i.e. {index: slice or hyperslab}
109
+ self.selection = {}
110
+ #: (:obj:`dict` <:obj:`str`, :obj:`str`>) \
111
+ #: shape of the source field, i.e. {index: length}
112
+ self.srclengths = {}
113
+ #: (:obj:`dict` <:obj:`str`, :obj:`str`>) \
114
+ #: source selection of the field,
115
+ #: i.e. {index: slice or hyperslab}
116
+ self.srcselection = {}
117
+ #: (:obj:`list` <:obj:`str`>) tag content
118
+ self.content = []
119
+ #: (:class:`nxswriter.DataSources.DataSource`) data source
120
+ self.source = None
121
+ #: (:obj:`str`) strategy, i.e. INIT, STEP, FINAL
122
+ self.strategy = 'STEP'
123
+ #: (:obj:`str`) trigger for asynchronous writting
124
+ self.trigger = None
125
+ self.error = ""
126
+ # virtual layout map
127
+ self.__vmap = {}
128
+
129
+ def setLength(self, index, value):
130
+ """ sets lengths dict element
131
+
132
+ :param index: length index
133
+ :type index: :obj:`int`
134
+ :param value: length value
135
+ :type value: :obj:`int` or :obj:`str`
136
+ """
137
+ self.lengths[index] = value
138
+
139
+ def setRank(self, rank):
140
+ """ sets dimension rank
141
+
142
+ :param index: dimension rank
143
+ :type index: :obj:`src`
144
+ """
145
+ self.rank = rank
146
+
147
+ def setSourceRank(self, rank):
148
+ """ sets dimension rank
149
+
150
+ :param index: dimension rank
151
+ :type index: :obj:`src`
152
+ """
153
+ self.srcrank = rank
154
+
155
+ def setSelection(self, index, value):
156
+ """ sets selection dict element
157
+
158
+ :param index: selection index
159
+ :type index: :obj:`int`
160
+ :param value: selection value
161
+ :type value: :obj:`int` or :obj:`str`
162
+ """
163
+ self.selection[index] = value
164
+
165
+ def setSourceLength(self, index, value):
166
+ """ sets source lengths dict element
167
+
168
+ :param index: length index
169
+ :type index: :obj:`int`
170
+ :param value: length value
171
+ :type value: :obj:`int` or :obj:`str`
172
+ """
173
+ self.srclengths[index] = value
174
+
175
+ def setSourceSelection(self, index, value):
176
+ """ sets source selection dict element
177
+
178
+ :param index: selection index
179
+ :type index: :obj:`int`
180
+ :param value: selection value
181
+ :type value: :obj:`int` or :obj:`str`
182
+ """
183
+ self.srcselection[index] = value
184
+
185
+ def __getShape(self):
186
+ """ provides shape
187
+
188
+ :returns: object shape
189
+ :rtype: :obj:`list` <:obj:`int` >
190
+ """
191
+ shape = []
192
+ try:
193
+ if int(self.rank) > 0:
194
+ for i in range(int(self.rank)):
195
+ si = str(i + 1)
196
+ if self.lengths and si in self.lengths.keys() \
197
+ and self.lengths[si] is not None:
198
+ if int(self.lengths[si]) > 0:
199
+ shape.append(int(self.lengths[si]))
200
+ else:
201
+ raise XMLSettingSyntaxError(
202
+ "Dimensions not defined")
203
+ if len(shape) < int(self.rank):
204
+ raise XMLSettingSyntaxError(
205
+ "Too small dimension number")
206
+ except XMLSettingSyntaxError:
207
+ if self.rank and int(self.rank) >= 0:
208
+ shape = [0] * (int(self.rank))
209
+ else:
210
+ shape = [0]
211
+ return shape
212
+
213
+ def __getKey(self):
214
+ """ provides key
215
+
216
+ :returns: object key
217
+ :rtype: :obj:`list` <:obj:`int` >
218
+ """
219
+ key = []
220
+ try:
221
+ if int(self.rank) > 0:
222
+ for i in range(int(self.rank)):
223
+ si = str(i + 1)
224
+ if self.selection and si in self.selection.keys() \
225
+ and self.selection[si] is not None:
226
+ key.append(self.selection[si])
227
+ else:
228
+ key.append(None)
229
+ except XMLSettingSyntaxError:
230
+ pass
231
+ return key
232
+
233
+ def __getSourceShape(self):
234
+ """ provides source shape
235
+
236
+ :returns: object shape
237
+ :rtype: :obj:`list` <:obj:`int` >
238
+ """
239
+ shape = []
240
+ try:
241
+ if int(self.srcrank) > 0:
242
+ for i in range(int(self.srcrank)):
243
+ si = str(i + 1)
244
+ if self.srclengths and si in self.srclengths.keys() \
245
+ and self.srclengths[si] is not None:
246
+ if int(self.srclengths[si]) > 0:
247
+ shape.append(int(self.srclengths[si]))
248
+ else:
249
+ raise XMLSettingSyntaxError(
250
+ "Dimensions not defined")
251
+ if len(shape) < int(self.srcrank):
252
+ raise XMLSettingSyntaxError(
253
+ "Too small dimension number")
254
+ except XMLSettingSyntaxError:
255
+ if self.srcrank and int(self.srcrank) >= 0:
256
+ shape = [0] * (int(self.srcrank))
257
+ else:
258
+ shape = [0]
259
+ return shape or None
260
+
261
+ def __getSourceKey(self):
262
+ """ provides source key
263
+
264
+ :returns: object key
265
+ :rtype: :obj:`list` <:obj:`int` >
266
+ """
267
+ key = []
268
+ try:
269
+ if int(self.srcrank) > 0:
270
+ for i in range(int(self.srcrank)):
271
+ si = str(i + 1)
272
+ if self.srcselection and si in self.srcselection.keys() \
273
+ and self.srcselection[si] is not None:
274
+ key.append(self.srcselection[si])
275
+ else:
276
+ key.append(None)
277
+ except XMLSettingSyntaxError:
278
+ pass
279
+ return key or None
280
+
281
+ def store(self, xml=None, globalJSON=None):
282
+ """ stores the tag content
283
+
284
+ :param xml: xml setting
285
+ :type xml: :obj: `str`
286
+ :param globalJSON: global JSON string
287
+ :type globalJSON: \
288
+ : :obj:`dict` <:obj:`str`, :obj:`dict` <:obj:`str`, any>>
289
+ """
290
+
291
+ shape = self.__getShape()
292
+ if shape:
293
+ self.__vmap["shape"] = shape
294
+ key = self.__getKey()
295
+ if key:
296
+ self.__vmap["key"] = key
297
+ srcshape = self.__getSourceShape()
298
+ if srcshape is not None:
299
+ self.__vmap["sourceshape"] = srcshape
300
+ srckey = self.__getSourceKey()
301
+ if srckey is not None:
302
+ self.__vmap["sourcekey"] = srckey
303
+ target = None
304
+ filename = None
305
+ fieldpath = None
306
+ if "name" in self._tagAttrs.keys():
307
+ self.__name = self._tagAttrs["name"]
308
+ if "target" in self._tagAttrs.keys():
309
+ if sys.version_info > (3,):
310
+ target = self._tagAttrs["target"]
311
+ else:
312
+ target = self._tagAttrs["target"].encode()
313
+ if target:
314
+ self.__vmap["target"] = target
315
+ if "filename" in self._tagAttrs.keys():
316
+ if sys.version_info > (3,):
317
+ filename = self._tagAttrs["filename"]
318
+ else:
319
+ filename = self._tagAttrs["filename"].encode()
320
+ if filename:
321
+ self.__vmap["filename"] = filename
322
+ if "fieldpath" in self._tagAttrs.keys():
323
+ if sys.version_info > (3,):
324
+ fieldpath = self._tagAttrs["fieldpath"]
325
+ else:
326
+ fieldpath = self._tagAttrs["fieldpath"].encode()
327
+ if fieldpath:
328
+ self.__vmap["fieldpath"] = fieldpath
329
+ if not self.source:
330
+ self.last.appendVmap(self.__vmap)
331
+ if self.source:
332
+ if self.source.isValid():
333
+ return self.strategy, self.trigger
334
+
335
+ def run(self):
336
+ """ runner
337
+
338
+ :brief: During its thread run it fetches the data from the source
339
+ """
340
+ try:
341
+ if self.source:
342
+ dt = self.source.getData()
343
+ if dt and isinstance(dt, dict):
344
+ dh = DataHolder(streams=self._streams, **dt)
345
+ val = dh.cast("string")
346
+ self.last.appendVmap(val, self.__vmap)
347
+
348
+ except Exception:
349
+ info = sys.exc_info()
350
+ import traceback
351
+ message = self.setMessage(
352
+ str(info[1].__str__()) + "\n " + (" ").join(
353
+ traceback.format_tb(sys.exc_info()[2])))
354
+ # message = self.setMessage( sys.exc_info()[1].__str__() )
355
+ del info
356
+ #: notification of error in the run method (defined in base class)
357
+ self.error = message
358
+ # self.error = sys.exc_info()
359
+ finally:
360
+ if self.error:
361
+ if self._streams:
362
+ if self.canfail:
363
+ self._streams.warn(
364
+ "EField::run() - %s " % str(self.error))
365
+ else:
366
+ self._streams.error(
367
+ "EField::run() - %s " % str(self.error))
368
+
369
+
370
+ class EVirtualField(FElementWithAttr):
371
+
372
+ """ virtual field H5 tag element
373
+ """
374
+
375
+ def __init__(self, attrs, last, streams=None,
376
+ reloadmode=False):
377
+ """ constructor
378
+
379
+ :param attrs: dictionary of the tag attributes
380
+ :type attrs: :obj:`dict` <:obj:`str`, :obj:`str`>
381
+ :param last: the last element from the stack
382
+ :type last: :class:`nxswriter.Element.Element`
383
+ :param streams: tango-like steamset class
384
+ :type streams: :class:`StreamSet` or :class:`tango.LatestDeviceImpl`
385
+ :param reloadmode: reload mode
386
+ :type reloadmode: :obj:`bool`
387
+ """
388
+ FElementWithAttr.__init__(self, "vds", attrs, last, streams=streams,
389
+ reloadmode=reloadmode)
390
+ #: (:obj:`str`) rank of the field
391
+ self.rank = "0"
392
+ #: (:obj:`dict` <:obj:`str`, :obj:`str`>) \
393
+ #: shape of the field, i.e. {index: length}
394
+ self.lengths = {}
395
+ #: (:obj:`str`) strategy, i.e. INIT, STEP, FINAL, POSTRUN
396
+ self.strategy = 'FINAL'
397
+ #: (:obj:`str`) trigger for asynchronous writing
398
+ self.trigger = None
399
+ #: (:obj:`str`) field data type
400
+ self.__dtype = ""
401
+ #: (:obj:`str`) field name
402
+ self.__name = ""
403
+ #: (:obj:`list` <:obj:`int` >) shape
404
+ self.__shape = []
405
+ #: (:obj:`list` <:obj:`dict` >) vmap list
406
+ self.__vmaps = []
407
+
408
+ def setRank(self, rank):
409
+ """ sets dimension rank
410
+
411
+ :param index: dimension rank
412
+ :type index: :obj:`src`
413
+ """
414
+ self.rank = rank
415
+
416
+ def setLength(self, index, value):
417
+ """ sets lengths dict element
418
+
419
+ :param index: length index
420
+ :type index: :obj:`int`
421
+ :param value: length value
422
+ :type value: :obj:`int` or :obj:`str`
423
+ """
424
+ self.lengths[index] = value
425
+
426
+ def __typeAndName(self):
427
+ """ provides type and name of the field
428
+
429
+ :returns: (type, name) tuple
430
+ """
431
+ if "name" in self._tagAttrs.keys():
432
+ nm = self._tagAttrs["name"]
433
+ if "type" in self._tagAttrs.keys():
434
+ tp = NTP.nTnp[self._tagAttrs["type"]]
435
+ else:
436
+ tp = "string"
437
+ return tp, nm
438
+ else:
439
+ if self._streams:
440
+ self._streams.error(
441
+ "FElement::__typeAndName() - Field without a name",
442
+ std=False)
443
+
444
+ raise XMLSettingSyntaxError("Field without a name")
445
+
446
+ def __getShape(self):
447
+ """ provides shape
448
+
449
+ :returns: object shape
450
+ :rtype: :obj:`list` <:obj:`int` >
451
+ """
452
+ try:
453
+ shape = self._findShape(
454
+ self.rank, self.lengths,
455
+ False, 0, True, checkData=True)
456
+ return shape
457
+ except XMLSettingSyntaxError:
458
+ if self.rank and int(self.rank) >= 0:
459
+ shape = [0] * (int(self.rank))
460
+ else:
461
+ shape = [0]
462
+ return shape
463
+
464
+ def __setAttributes(self):
465
+ """ creates attributes
466
+
467
+ :brief: It creates attributes in h5Object
468
+ """
469
+ self._setAttributes(["name"])
470
+ self._createAttributes()
471
+
472
+ if self.strategy == "POSTRUN":
473
+ if sys.version_info > (3,):
474
+ self.h5Object.attributes.create(
475
+ "postrun",
476
+ "string", overwrite=True)[...] \
477
+ = self.postrun.strip()
478
+ else:
479
+ self.h5Object.attributes.create(
480
+ "postrun".encode(),
481
+ "string".encode(), overwrite=True)[...] \
482
+ = self.postrun.encode().strip()
483
+
484
+ def __setStrategy(self, name):
485
+ """ provides strategy or fill the value in
486
+
487
+ :param name: object name
488
+ :returns: strategy or strategy,trigger it trigger defined
489
+ """
490
+ if self.source:
491
+ if self.source.isValid():
492
+ return self.strategy, self.trigger
493
+ if sys.version_info > (3,):
494
+ val = ("".join(self.content)).strip()
495
+ else:
496
+ val = ("".join(self.content)).strip().encode()
497
+ if val:
498
+ lval = val.split("\n")
499
+ for el in lval:
500
+ if el.strip():
501
+ self.__vmaps.append({"target": el.strip()})
502
+ return self.strategy, self.trigger
503
+
504
+ def store(self, xml=None, globalJSON=None):
505
+ """ stores the tag content
506
+
507
+ :param xml: xml setting
508
+ :type xml: :obj:`str`
509
+ :param globalJSON: global JSON string
510
+ :type globalJSON: \
511
+ : :obj:`dict` <:obj:`str`, :obj:`dict` <:obj:`str`, any>>
512
+ :returns: (strategy, trigger)
513
+ :rtype: (:obj:`str`, :obj:`str`)
514
+ """
515
+
516
+ # type and name
517
+ self.__dtype, self.__name = self.__typeAndName()
518
+ # shape
519
+ self.__shape = self.__getShape()
520
+ return self.__setStrategy(self.__name)
521
+
522
+ def __cureKeys(self, key):
523
+ tkey = []
524
+ if isinstance(key, list):
525
+ try:
526
+ sk = list(set([len(ky) for ky in key]))
527
+ except Exception:
528
+ sk = []
529
+ if len(sk) == 1 and sk[0] == 4:
530
+ offset = []
531
+ block = []
532
+ count = []
533
+ stride = []
534
+ for ky in key:
535
+ off, bl, cnt, std = ky
536
+ offset.append(off)
537
+ block.append(bl)
538
+ count.append(cnt)
539
+ stride.append(std)
540
+ return FileWriter.FTHyperslab(offset, block, count, stride)
541
+ for ky in key:
542
+ if isinstance(ky, list) and len(ky) > 0 and len(ky) < 4:
543
+ tkey.append(slice(*ky))
544
+ else:
545
+ if ky is None:
546
+ ky = slice(None)
547
+ tkey.append(ky)
548
+
549
+ return tuple(tkey)
550
+ return key
551
+
552
+ def appendVmap(self, values, base=None):
553
+ """ append virtual map items
554
+
555
+ :param values: a list of map items to append
556
+ :type values: :obj:`str` or :obj:`list`< :obj:`str` >
557
+ or :obj:`list`< :obj:`dict` >
558
+ :param base: base map item to append
559
+ :type base: :obj:`dict`
560
+ """
561
+ if hasattr(values, "shape") and values.shape == tuple():
562
+ values = str(values)
563
+ try:
564
+ if isinstance(values, str):
565
+ values = json.loads(values)
566
+ if not isinstance(values, list):
567
+ values = [values]
568
+ except Exception:
569
+ if hasattr(values, "flatten"):
570
+ values = values.flatten()
571
+ if isinstance(values, str):
572
+ values = [values]
573
+ val = values
574
+ values = []
575
+ for vl in val:
576
+ try:
577
+ if isinstance(vl, str):
578
+ vl = json.loads(vl)
579
+ values.append(vl)
580
+ except Exception:
581
+ values.append(str(vl).strip())
582
+ for vl in values:
583
+ if isinstance(base, dict):
584
+ fval = dict(base)
585
+ else:
586
+ fval = {}
587
+ if isinstance(vl, dict):
588
+ fval.update(vl)
589
+ else:
590
+ fval.update({"target": vl.strip()})
591
+ self.__vmaps.append(fval)
592
+ return len(self.__vmaps)
593
+
594
+ def __findShape(self, key, eshape=None, unlimited=True):
595
+ if isinstance(key, FileWriter.FTHyperslab):
596
+ if not unlimited:
597
+ count = [(ct if ct != FileWriter.writer.unlimited() else 1)
598
+ for ct in key.count]
599
+
600
+ block = [(ct if ct != FileWriter.writer.unlimited() else 1)
601
+ for ct in key.block]
602
+ else:
603
+ count = key.count
604
+ block = key.block
605
+ eshape = [bl * count[hi] for hi, bl in enumerate(block)]
606
+ if isinstance(key, tuple):
607
+ eshape = []
608
+ for ky in key:
609
+ if not unlimited and ky.stop == FileWriter.writer.unlimited():
610
+ eshape.append(1)
611
+ elif isinstance(ky, slice) and ky.stop > 0:
612
+ start = ky.start if ky.start is not None else 0
613
+ step = ky.step if ky.step is not None else 1
614
+ eshape.append((ky.stop - start) // step)
615
+ else:
616
+ eshape.append(1)
617
+ return eshape
618
+
619
+ def __createVDS(self):
620
+ """ create the virtual field object
621
+ """
622
+ vlf = FileWriter.virtual_field_layout(
623
+ self.__shape, self.__dtype)
624
+ counter = 0
625
+ for vmap in self.__vmaps:
626
+ fieldpath = ""
627
+ filename = ""
628
+ edtype = vmap["dtype"] \
629
+ if "dtype" in vmap else self.__dtype
630
+ key = vmap["key"] if "key" in vmap else counter
631
+ key = self.__cureKeys(key)
632
+ if "shape" in vmap:
633
+ eshape = vmap["shape"]
634
+ elif isinstance(key, int):
635
+ eshape = list(self.__shape)
636
+ eshape[0] = 1
637
+ else:
638
+ eshape = [0] * len(self.__shape)
639
+ fieldpath = vmap["fieldpath"] \
640
+ if "fieldpath" in vmap else "/data"
641
+ filename = vmap["filename"] if "filename" in vmap else None
642
+ if "target" in vmap:
643
+ target = vmap["target"]
644
+ if target.startswith("h5file:/"):
645
+ target = target[8:]
646
+ if "::" in target:
647
+ filename, fieldpath = target.split("::")
648
+ elif ":/" in target:
649
+ filename, fieldpath = target.split(":/")
650
+ else:
651
+ fieldpath = target
652
+ obj = self._lastObject()
653
+ while filename is None:
654
+ par = obj.parent
655
+ if par is None:
656
+ break
657
+ if hasattr(par, "root") and hasattr(par, "name"):
658
+ filename = par.name
659
+ break
660
+ else:
661
+ obj = par
662
+ sourceshape = vmap["sourceshape"] \
663
+ if "sourceshape" in vmap else None
664
+ sourcekey = vmap["sourcekey"] \
665
+ if "sourcekey" in vmap else None
666
+ sourcekey = self.__cureKeys(sourcekey)
667
+ if not any(eshape):
668
+ eshape = self.__findShape(key, eshape, unlimited=False)
669
+ ef = FileWriter.target_field_view(
670
+ filename, fieldpath, eshape, edtype)
671
+ if eshape:
672
+ counter += eshape[0]
673
+ else:
674
+ counter += 1
675
+ # print("KEY", key, sourcekey, sourceshape, eshape)
676
+ vlf.add(key, ef, sourcekey, sourceshape)
677
+ self.h5Object = self._lastObject().create_virtual_field(
678
+ self.__name, vlf)
679
+
680
+ def run(self):
681
+ """ runner
682
+
683
+ :brief: During its thread run it fetches the data from the source
684
+ """
685
+ try:
686
+ if self.source:
687
+ dt = self.source.getData()
688
+ if dt and isinstance(dt, dict):
689
+ dh = DataHolder(streams=self._streams, **dt)
690
+ val = dh.cast("string")
691
+ self.appendVmap(val)
692
+ # print("VMAPS", self.__vmaps)
693
+ # print("SHaPE", self.__shape)
694
+ # print("TYPE", self.__dtype)
695
+ # print("NAME", self.__name)
696
+ if self.__vmaps and self.__shape and self.__dtype and self.__name:
697
+ self.__createVDS()
698
+ self.__setAttributes()
699
+ except Exception:
700
+ info = sys.exc_info()
701
+ import traceback
702
+ message = self.setMessage(
703
+ str(info[1].__str__()) + "\n " + (" ").join(
704
+ traceback.format_tb(sys.exc_info()[2])))
705
+ # message = self.setMessage( sys.exc_info()[1].__str__() )
706
+ del info
707
+ #: notification of error in the run method (defined in base class)
708
+ self.error = message
709
+ # self.error = sys.exc_info()
710
+ finally:
711
+ if self.error:
712
+ if self._streams:
713
+ if self.canfail:
714
+ self._streams.warn(
715
+ "EField::run() - %s " % str(self.error))
716
+ else:
717
+ self._streams.error(
718
+ "EField::run() - %s " % str(self.error))
nxswriter/FElement.py CHANGED
@@ -195,7 +195,7 @@ class FElement(Element):
195
195
  if sys.version_info > (3,):
196
196
  val = ("".join(self.content)).strip()
197
197
  else:
198
- val = ("".join(self.content)).strip().encode()
198
+ val = ("".join(self.content)).strip().encode("utf8")
199
199
  found = False
200
200
  if checkData and self.source and self.source.isValid():
201
201
  data = self.source.getData()
@@ -497,9 +497,12 @@ class FElementWithAttr(FElement):
497
497
  ekey, "string", overwrite=True)[...] \
498
498
  = self._tagAttrs[key].strip()
499
499
  else:
500
+ try:
501
+ vl = self._tagAttrs[key].strip().encode()
502
+ except Exception:
503
+ vl = self._tagAttrs[key].strip().encode("utf8")
500
504
  self.h5Object.attributes.create(
501
- ekey, "string", overwrite=True)[...] \
502
- = self._tagAttrs[key].strip().encode()
505
+ ekey, "string", overwrite=True)[...] = vl
503
506
 
504
507
  def h5Attribute(self, name):
505
508
  """ provides attribute h5 object
nxswriter/H5Elements.py CHANGED
@@ -19,6 +19,8 @@
19
19
 
20
20
  """ Definitions of tag evaluation classes """
21
21
 
22
+ import json
23
+
22
24
  from .Element import Element
23
25
  from .FElement import FElement
24
26
  from .DataHolder import DataHolder
@@ -125,7 +127,27 @@ class EDimensions(Element):
125
127
  """
126
128
  Element.__init__(self, "dimensions", attrs, last, streams=streams)
127
129
  if "rank" in attrs.keys():
128
- self.last.rank = attrs["rank"]
130
+ self.last.setRank(attrs["rank"])
131
+
132
+
133
+ class ESelection(Element):
134
+
135
+ """ selection tag element
136
+ """
137
+
138
+ def __init__(self, attrs, last, streams=None):
139
+ """ constructor
140
+
141
+ :param attrs: dictionary of the tag attributes
142
+ :type attrs: :obj:`dict` <:obj:`str`, :obj:`str`>
143
+ :param last: the last element from the stack
144
+ :type last: :class:`nxswriter.Element.Element`
145
+ :param streams: tango-like steamset class
146
+ :type streams: :class:`StreamSet` or :class:`tango.LatestDeviceImpl`
147
+ """
148
+ Element.__init__(self, "selection", attrs, last, streams=streams)
149
+ if "rank" in attrs.keys():
150
+ self.last.setRank(attrs["rank"])
129
151
 
130
152
 
131
153
  class EDim(Element):
@@ -145,7 +167,147 @@ class EDim(Element):
145
167
  """
146
168
  Element.__init__(self, "dim", attrs, last, streams=streams)
147
169
  if ("index" in attrs.keys()) and ("value" in attrs.keys()):
148
- self._beforeLast().lengths[attrs["index"]] = attrs["value"]
170
+ self._beforeLast().setLength(attrs["index"], attrs["value"])
171
+ #: (:obj:`str`) index attribute
172
+ self.__index = None
173
+ #: (:class:`nxswriter.DataSources.DataSource`) data source
174
+ self.source = None
175
+ #: (:obj:`list` <:obj:`str`>) tag content
176
+ self.content = []
177
+ if "index" in attrs.keys():
178
+ self.__index = attrs["index"]
179
+
180
+ def store(self, xml=None, globalJSON=None):
181
+ """ stores the tag content
182
+
183
+ :param xml: xml setting
184
+ :type xml: :obj: `str`
185
+ :param globalJSON: global JSON string
186
+ :type globalJSON: \
187
+ : :obj:`dict` <:obj:`str`, :obj:`dict` <:obj:`str`, any>>
188
+ """
189
+ if self.__index is not None and self.source:
190
+ dt = self.source.getData()
191
+ if dt and isinstance(dt, dict):
192
+ dh = DataHolder(streams=self._streams, **dt)
193
+ if dh:
194
+ self._beforeLast().setLength(self.__index,
195
+ str(dh.cast("string")))
196
+
197
+
198
+ class ESlab(Element):
199
+
200
+ """ slab tag element
201
+ """
202
+
203
+ def __init__(self, attrs, last, streams=None):
204
+ """ constructor
205
+
206
+ :param attrs: dictionary of the tag attributes
207
+ :type attrs: :obj:`dict` <:obj:`str`, :obj:`str`>
208
+ :param last: the last element from the stack
209
+ :type last: :class:`nxswriter.Element.Element`
210
+ :param streams: tango-like steamset class
211
+ :type streams: :class:`StreamSet` or :class:`tango.LatestDeviceImpl`
212
+ """
213
+ Element.__init__(self, "slab", attrs, last, streams=streams)
214
+ if ("index" in attrs.keys()):
215
+ offset = 0
216
+ block = 1
217
+ count = 1
218
+ stride = 1
219
+ if "offset" in attrs.keys() and attrs["offset"]:
220
+ try:
221
+ offset = int(attrs["offset"])
222
+ except Exception:
223
+ pass
224
+ if "block" in attrs.keys() and attrs["block"]:
225
+ try:
226
+ block = int(attrs["block"])
227
+ except Exception:
228
+ pass
229
+ if "count" in attrs.keys() and attrs["count"]:
230
+ try:
231
+ count = int(attrs["count"])
232
+ except Exception:
233
+ pass
234
+ if "stride" in attrs.keys() and attrs["stride"]:
235
+ try:
236
+ stride = int(attrs["stride"])
237
+ except Exception:
238
+ pass
239
+ self._beforeLast().setSelection(
240
+ attrs["index"], [offset, block, count, stride])
241
+ #: (:obj:`str`) index attribute
242
+ self.__index = None
243
+ #: (:class:`nxswriter.DataSources.DataSource`) data source
244
+ self.source = None
245
+ #: (:obj:`list` <:obj:`str`>) tag content
246
+ self.content = []
247
+ if "index" in attrs.keys():
248
+ self.__index = attrs["index"]
249
+
250
+ def store(self, xml=None, globalJSON=None):
251
+ """ stores the tag content
252
+
253
+ :param xml: xml setting
254
+ :type xml: :obj: `str`
255
+ :param globalJSON: global JSON string
256
+ :type globalJSON: \
257
+ : :obj:`dict` <:obj:`str`, :obj:`dict` <:obj:`str`, any>>
258
+ """
259
+ if self.__index is not None and self.source:
260
+ dt = self.source.getData()
261
+ if dt and isinstance(dt, dict):
262
+ dh = DataHolder(streams=self._streams, **dt)
263
+ if dh:
264
+ slab = json.loads(str(dh.cast("string")))
265
+ if isinstance(slab, list):
266
+ self._beforeLast().setSelection(self.__index, slab[:4])
267
+
268
+
269
+ class ESlice(Element):
270
+
271
+ """ slice tag element
272
+ """
273
+
274
+ def __init__(self, attrs, last, streams=None):
275
+ """ constructor
276
+
277
+ :param attrs: dictionary of the tag attributes
278
+ :type attrs: :obj:`dict` <:obj:`str`, :obj:`str`>
279
+ :param last: the last element from the stack
280
+ :type last: :class:`nxswriter.Element.Element`
281
+ :param streams: tango-like steamset class
282
+ :type streams: :class:`StreamSet` or :class:`tango.LatestDeviceImpl`
283
+ """
284
+ Element.__init__(self, "slice", attrs, last, streams=streams)
285
+ if ("index" in attrs.keys()):
286
+ added = False
287
+ start = None
288
+ stop = None
289
+ step = None
290
+ if "start" in attrs.keys() and attrs["start"]:
291
+ try:
292
+ start = int(attrs["start"])
293
+ added = True
294
+ except Exception:
295
+ pass
296
+ if "stop" in attrs.keys() and attrs["stop"]:
297
+ try:
298
+ stop = int(attrs["stop"])
299
+ added = True
300
+ except Exception:
301
+ pass
302
+ if "step" in attrs.keys() and attrs["step"]:
303
+ try:
304
+ step = int(attrs["step"])
305
+ added = True
306
+ except Exception:
307
+ pass
308
+ if added:
309
+ self._beforeLast().setSelection(
310
+ attrs["index"], slice(start, stop, step))
149
311
  #: (:obj:`str`) index attribute
150
312
  self.__index = None
151
313
  #: (:class:`nxswriter.DataSources.DataSource`) data source
@@ -169,8 +331,10 @@ class EDim(Element):
169
331
  if dt and isinstance(dt, dict):
170
332
  dh = DataHolder(streams=self._streams, **dt)
171
333
  if dh:
172
- self._beforeLast().lengths[self.__index] = str(
173
- dh.cast("string"))
334
+ lslice = json.loads(str(dh.cast("string")))
335
+ if isinstance(lslice, list):
336
+ self._beforeLast().setSelection(
337
+ self.__index, slice(*lslice))
174
338
 
175
339
 
176
340
  class EFilter(Element):
@@ -28,11 +28,13 @@ from .Element import Element
28
28
  from .FElement import FElement
29
29
  from .EGroup import EGroup
30
30
  from .EField import EField
31
+ from .EVirtualField import EVirtualField, EVirtualDataMap, EVirtualSourceView
31
32
  from .EAttribute import EAttribute
32
33
  from .EStrategy import EStrategy
33
34
  from .ELink import ELink
34
35
  from .H5Elements import (
35
- EDoc, ESymbol, EDimensions, EDim, EFile, EFilter)
36
+ EDoc, ESymbol, EDimensions, EDim, EFile, EFilter, ESlab, ESlice,
37
+ ESelection)
36
38
  from .DataSourceFactory import DataSourceFactory
37
39
  from .ThreadPool import ThreadPool
38
40
  from .InnerXMLParser import InnerXMLHandler
@@ -121,7 +123,10 @@ class NexusXMLHandler(sax.ContentHandler):
121
123
  'symbols': Element, 'symbol': ESymbol,
122
124
  'dimensions': EDimensions, 'dim': EDim,
123
125
  'enumeration': Element, 'item': Element,
124
- 'strategy': EStrategy, 'filter': EFilter
126
+ 'strategy': EStrategy, 'filter': EFilter,
127
+ 'vds': EVirtualField, 'map': EVirtualDataMap,
128
+ 'sourceview': EVirtualSourceView,
129
+ 'slab': ESlab, 'slice': ESlice, 'selection': ESelection,
125
130
  }
126
131
 
127
132
  #: (:obj:`list` <:obj:`dict` <:obj:`str`, :obj:`str` > >) \
@@ -130,7 +135,7 @@ class NexusXMLHandler(sax.ContentHandler):
130
135
 
131
136
  #: (:obj:`dict` <:obj:`str`, :obj:`type` > ) \
132
137
  #: map of tag names to related classes
133
- self.withAttr = ['group', 'field']
138
+ self.withAttr = ['group', 'field', 'vds']
134
139
 
135
140
  #: (:obj:`list` <:obj:`str`>) transparent tags
136
141
  self.transparentTags = ['definition']
nxswriter/Release.py CHANGED
@@ -21,4 +21,4 @@
21
21
 
22
22
 
23
23
  #: package version
24
- __version__ = "3.11.1"
24
+ __version__ = "3.14.0"
@@ -71,6 +71,7 @@ DEFAULTWRITERS = ["h5cpp", "h5py", "h5redis"]
71
71
  #: (:obj:`bool`) tango bug #213 flag related to EncodedAttributes in python3
72
72
  PYTG_BUG_213 = False
73
73
  if sys.version_info > (3,):
74
+ unicode = str
74
75
  try:
75
76
  try:
76
77
  import tango
@@ -315,9 +316,12 @@ class TangoDataWriter(object):
315
316
  """
316
317
  self.__fetcher = FetchNameHandler(streams=self._streams)
317
318
  if sys.version_info > (3,):
318
- sax.parseString(bytes(xmlset, 'utf-8'), self.__fetcher)
319
- else:
320
319
  sax.parseString(xmlset, self.__fetcher)
320
+ else:
321
+ if isinstance(xmlset, unicode):
322
+ sax.parseString(xmlset.encode('utf-8'), self.__fetcher)
323
+ else:
324
+ sax.parseString(xmlset, self.__fetcher)
321
325
  self.__xmlsettings = xmlset
322
326
 
323
327
  def __delXML(self):
@@ -437,8 +441,7 @@ class TangoDataWriter(object):
437
441
  if self.addingLogs:
438
442
  name = "nexus_logs"
439
443
  if not self.__nxRoot.exists(name):
440
- ngroup = self.__nxRoot.create_group(
441
- name, "NXcollection")
444
+ ngroup = self.__nxRoot.create_group(name)
442
445
  else:
443
446
  ngroup = self.__nxRoot.open(name)
444
447
  name = "configuration"
@@ -452,8 +455,7 @@ class TangoDataWriter(object):
452
455
  error = False
453
456
  else:
454
457
  counter += 1
455
- self.__logGroup = ngroup.create_group(
456
- cname, "NXcollection")
458
+ self.__logGroup = ngroup.create_group(cname)
457
459
  vfield = self.__logGroup.create_field(
458
460
  "python_version", "string")
459
461
  vfield.write(str(sys.version))
@@ -506,7 +508,15 @@ class TangoDataWriter(object):
506
508
  parser.setContentHandler(handler)
507
509
  parser.setErrorHandler(errorHandler)
508
510
  inpsrc = sax.InputSource()
509
- inpsrc.setByteStream(StringIO(self.xmlsettings))
511
+ if sys.version_info > (3,):
512
+ inpsrc.setByteStream(StringIO(self.xmlsettings))
513
+ else:
514
+ if isinstance(self.xmlsettings, unicode):
515
+ inpsrc.setByteStream(
516
+ StringIO(self.xmlsettings.encode('utf-8')))
517
+ else:
518
+ inpsrc.setByteStream(StringIO(self.xmlsettings))
519
+
510
520
  parser.parse(inpsrc)
511
521
 
512
522
  self.__initPool = handler.initPool
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nxswriter
3
- Version: 3.11.1
3
+ Version: 3.14.0
4
4
  Summary: Nexus Data writer implemented as a Tango Server
5
5
  Home-page: https://github.com/nexdatas/nxsdatawriter
6
6
  Author: Jan Kotanski, Eugen Wintersberger , Halil Pasic
@@ -21,6 +21,8 @@ Classifier: Programming Language :: Python :: 3.7
21
21
  Classifier: Programming Language :: Python :: 3.8
22
22
  Classifier: Programming Language :: Python :: 3.9
23
23
  Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Programming Language :: Python :: 3.12
24
26
  Requires-Dist: lxml
25
27
  Requires-Dist: numpy (>1.6.0)
26
28
  Requires-Dist: nxstools (>=3.50.0)
@@ -87,12 +89,12 @@ Extract sources and run
87
89
 
88
90
  .. code-block:: console
89
91
 
90
- $ python setup.py install
92
+ $ python3 setup.py install
91
93
 
92
94
  Debian packages
93
95
  """""""""""""""
94
96
 
95
- Debian `bookworm`, `bullseye`, `buster` or Ubuntu `lunar`, `jammy`, `focal` packages can be found in the HDRI repository.
97
+ Debian `bookworm`, `bullseye`, `buster` or Ubuntu `oracular`, `noble`, `jammy` packages can be found in the HDRI repository.
96
98
 
97
99
  To install the debian packages, add the PGP repository key
98
100
 
@@ -173,7 +175,7 @@ To set up NeXus Writer Server run
173
175
 
174
176
  $ nxsetup -x NXSDataWriter
175
177
 
176
- The *nxsetup* command comes from the **python-nxstools** package.
178
+ The *nxsetup* command comes from the **python3-nxstools** package.
177
179
 
178
180
  -----------
179
181
  Client code
@@ -5,33 +5,34 @@ nxswriter/DataSourceFactory.py,sha256=W0IirDjsu38KKvBxFbkvv-ghvqil2JJStQ3WMxo8Kh
5
5
  nxswriter/DataSourcePool.py,sha256=1bDOrHhYpG_ZFz8ut2IzkNSMeGxrCBcSCneM4h1AgDc,4574
6
6
  nxswriter/DataSources.py,sha256=l40n4WTfgRjLpFsJs7JoWjsER_dCVviRI_iolQ2fENM,5303
7
7
  nxswriter/DecoderPool.py,sha256=8nsKtzwyls-YLZUJAfxdGrqb2278Er1Y20NVq1XexvY,15052
8
- nxswriter/EAttribute.py,sha256=8i3EaIQbXWkt7zGOuu1RjGIZ7slbgxIgaGJDWVyUAOU,8434
9
- nxswriter/EField.py,sha256=ELCyQ9K6EhvLEJICnUMHzYTumMRM_b9xXHbXMqQOwgA,27653
8
+ nxswriter/EAttribute.py,sha256=hADI-LeuQMZwVoTFM4qevoz173Ma_atrk0edqvsFXS0,8878
9
+ nxswriter/EField.py,sha256=YLbdaykGccZ4cjqheS9te50FG6HQq5kfp7gg_OBkJ9k,28034
10
10
  nxswriter/EGroup.py,sha256=Y_PuTERckQXfUXGISbnpzHj7I4y2iFxM5CGByjVD6KA,4900
11
11
  nxswriter/ELink.py,sha256=FO7SRF1bpJhqRzK2FBSkRHhFwH1Mw5BRCgt8X8qJbr0,8820
12
12
  nxswriter/EStrategy.py,sha256=3RX8E6Ee-Klv9DGlMPvXJacdNDmuKWLQrcnuerR0IQI,3992
13
+ nxswriter/EVirtualField.py,sha256=ZECzyGb4wZoBohHlwkcilpOtDHuA907VoruLDe9RN9k,24971
13
14
  nxswriter/Element.py,sha256=dnIUS_U0fqJK3FxV_raQBx6qTGPT7sUFkWVzxI5YuEY,3019
14
15
  nxswriter/ElementThread.py,sha256=gCZRpzjji8TRfWLkwFRXG_K55d0yUkv9Gzi2DZ22EyQ,2099
15
16
  nxswriter/Errors.py,sha256=dYXtJ7rVWv59kAalNMMZO4X3SxSplhoWICeCb3_rFGc,1660
16
- nxswriter/FElement.py,sha256=dwc9wkMjhlueIdVIPSFmELje4VHtHFwS2UwTWbJs7Is,20463
17
+ nxswriter/FElement.py,sha256=ebQT2HHPmR6_J8H8ILa7G-gMDDNrEIUNh7sIfm9SF1I,20622
17
18
  nxswriter/FetchNameHandler.py,sha256=WbIJcxB9wjUHAIgXpZOzxBBAlWMhg-zYiLw_2sxcBIY,6829
18
- nxswriter/H5Elements.py,sha256=V5judPZZM6em5SgjILwZDfnND8Mk7JntAFIivAkgqL8,7420
19
+ nxswriter/H5Elements.py,sha256=64BFlgfaPEuRzWyWjkdfMhwF6oMc_NzAqAoKaZGAigo,13263
19
20
  nxswriter/InnerXMLParser.py,sha256=Cr5Ih-51LGi8sKQi1qUUikL2K5hjwwilJo-j1kWHgds,4493
20
21
  nxswriter/Metadata.py,sha256=Qg5KdlreERGG5CTZrCRAJXwBXxg96toyZ8wkknmdB3s,3668
21
22
  nxswriter/NXSFromXML.py,sha256=932BivWZnf-3tnIkbpSRFwfGV0PTwcT9pYb2FMmVd_4,9077
22
23
  nxswriter/NXSWriter.py,sha256=raHykC9mpUXU8pPtsqePuz3CI-24qYjIUSoyux2zCgo,31345
23
- nxswriter/NexusXMLHandler.py,sha256=QxSB6Nwi-6ZWR0SxTOojfcF99kN4MBRVNIGKeN7p2Ug,13841
24
+ nxswriter/NexusXMLHandler.py,sha256=IrZ2mWLuovdBIHcWTqKmr4HZxpMEWLun8A94O6pavr8,14131
24
25
  nxswriter/PyEvalSource.py,sha256=7-7Gc2_3CGd3XMHD3LBPCBOZx4Q6b1guzt1xgrSLxMs,11234
25
- nxswriter/Release.py,sha256=tBHpdqc23vJCmyEuudXIzQ8d8ZDQFktG5-hBf86ZmAE,900
26
+ nxswriter/Release.py,sha256=qNmln5Ifl--7uY5SpcQDkGFLFbqPVDYTmjV_3yQqLQI,900
26
27
  nxswriter/StreamSet.py,sha256=sSvXJxoDufmt9_Xu5rFaQsp_4x9gww_zMv0NTiiyLlg,5799
27
- nxswriter/TangoDataWriter.py,sha256=IYhi8qoDzyIaBAta15MlF3py9kq3dZdE0_jHMFiO7RU,28333
28
+ nxswriter/TangoDataWriter.py,sha256=yP6B3TVUhpHp8OBHKYQRNNtFer9xARoakNXuro4eVv8,28725
28
29
  nxswriter/TangoSource.py,sha256=jiFGUsoX2N5-i2gpBqkHi2KjmTBd46TI22Cjkt_2btw,29410
29
30
  nxswriter/ThreadPool.py,sha256=TKvOStVUUyuyHowk0MRaBM4GmRKtl0VPVVPdFHu332M,6039
30
31
  nxswriter/Types.py,sha256=CY_qw5-pbbDutRErgA6hbUTh903QA_IXc-CGSfuBje8,7676
31
32
  nxswriter/__init__.py,sha256=M0w3HGjZgfdqjMdQNaLcq5jazqQeRekx84YSbQCA8-0,1760
32
- nxswriter-3.11.1.data/scripts/NXSDataWriter,sha256=wO3opCCjYttfrY7CITNXHvirXv5W6rIQTY7vX5PmioI,905
33
- nxswriter-3.11.1.data/scripts/nxsfromxml,sha256=qxnJUtV_ueA3lGnne8ltaOF6yF5YtmzeFLIl3NWkAq8,61
34
- nxswriter-3.11.1.dist-info/METADATA,sha256=DT7d4_jKn2J8Tr69mbJBvqLAf8qzNpQ7-YbJfrD5Vo8,8856
35
- nxswriter-3.11.1.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
36
- nxswriter-3.11.1.dist-info/top_level.txt,sha256=29dYcOYN2MVz1NKpwobc4Zl4yjhd4VB62LDSuSy7x0Y,10
37
- nxswriter-3.11.1.dist-info/RECORD,,
33
+ nxswriter-3.14.0.data/scripts/NXSDataWriter,sha256=wO3opCCjYttfrY7CITNXHvirXv5W6rIQTY7vX5PmioI,905
34
+ nxswriter-3.14.0.data/scripts/nxsfromxml,sha256=qxnJUtV_ueA3lGnne8ltaOF6yF5YtmzeFLIl3NWkAq8,61
35
+ nxswriter-3.14.0.dist-info/METADATA,sha256=53Fc3OKmRlNatTbdcs0-lhBae1UoQkkPWLDvY_KAshY,8964
36
+ nxswriter-3.14.0.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
37
+ nxswriter-3.14.0.dist-info/top_level.txt,sha256=29dYcOYN2MVz1NKpwobc4Zl4yjhd4VB62LDSuSy7x0Y,10
38
+ nxswriter-3.14.0.dist-info/RECORD,,