dcnum 0.25.2__py3-none-any.whl → 0.25.4__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.
Potentially problematic release.
This version of dcnum might be problematic. Click here for more details.
- dcnum/_version.py +2 -2
- dcnum/feat/feat_background/bg_roll_median.py +10 -0
- dcnum/feat/feat_background/bg_sparse_median.py +10 -0
- dcnum/feat/queue_event_extractor.py +8 -0
- dcnum/logic/ctrl.py +0 -27
- dcnum/os_env_st.py +85 -0
- dcnum/read/hdf5_data.py +5 -2
- dcnum/segm/segmenter_mpo.py +10 -1
- {dcnum-0.25.2.dist-info → dcnum-0.25.4.dist-info}/METADATA +1 -1
- {dcnum-0.25.2.dist-info → dcnum-0.25.4.dist-info}/RECORD +13 -12
- {dcnum-0.25.2.dist-info → dcnum-0.25.4.dist-info}/WHEEL +1 -1
- {dcnum-0.25.2.dist-info → dcnum-0.25.4.dist-info}/LICENSE +0 -0
- {dcnum-0.25.2.dist-info → dcnum-0.25.4.dist-info}/top_level.txt +0 -0
dcnum/_version.py
CHANGED
|
@@ -4,6 +4,8 @@ import time
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
from scipy import ndimage
|
|
6
6
|
|
|
7
|
+
from ...os_env_st import RequestSingleThreaded, confirm_single_threaded
|
|
8
|
+
|
|
7
9
|
from .base import mp_spawn, Background
|
|
8
10
|
|
|
9
11
|
|
|
@@ -241,6 +243,8 @@ class WorkerRollMed(mp_spawn.Process):
|
|
|
241
243
|
|
|
242
244
|
def run(self):
|
|
243
245
|
"""Main loop of worker process (breaks when `self.counter` <0)"""
|
|
246
|
+
# confirm single-threadedness (prints to log)
|
|
247
|
+
confirm_single_threaded()
|
|
244
248
|
# Create the ctypes arrays here instead of during __init__, because
|
|
245
249
|
# for some reason they are copied in __init__ and not mapped.
|
|
246
250
|
shared_input = np.ctypeslib.as_array(
|
|
@@ -261,6 +265,12 @@ class WorkerRollMed(mp_spawn.Process):
|
|
|
261
265
|
with self.counter.get_lock():
|
|
262
266
|
self.counter.value += 1
|
|
263
267
|
|
|
268
|
+
def start(self):
|
|
269
|
+
# Set all relevant os environment variables such libraries in the
|
|
270
|
+
# new process only use single-threaded computation.
|
|
271
|
+
with RequestSingleThreaded():
|
|
272
|
+
mp_spawn.Process.start(self)
|
|
273
|
+
|
|
264
274
|
|
|
265
275
|
def compute_median_for_slice(shared_input, shared_output, kernel_size,
|
|
266
276
|
output_size, job_slice):
|
|
@@ -6,6 +6,8 @@ from scipy import ndimage
|
|
|
6
6
|
|
|
7
7
|
from ...read import HDF5Data
|
|
8
8
|
|
|
9
|
+
from ...os_env_st import RequestSingleThreaded, confirm_single_threaded
|
|
10
|
+
|
|
9
11
|
from .base import mp_spawn, Background
|
|
10
12
|
|
|
11
13
|
|
|
@@ -436,6 +438,8 @@ class WorkerSparseMed(mp_spawn.Process):
|
|
|
436
438
|
|
|
437
439
|
def run(self):
|
|
438
440
|
"""Main loop of worker process (breaks when `self.counter` <0)"""
|
|
441
|
+
# confirm single-threadedness (prints to log)
|
|
442
|
+
confirm_single_threaded()
|
|
439
443
|
# Create the ctypes arrays here instead of during __init__, because
|
|
440
444
|
# for some reason they are copied in __init__ and not mapped.
|
|
441
445
|
shared_input = np.ctypeslib.as_array(
|
|
@@ -468,3 +472,9 @@ class WorkerSparseMed(mp_spawn.Process):
|
|
|
468
472
|
# overwrite_input=False)
|
|
469
473
|
with self.counter.get_lock():
|
|
470
474
|
self.counter.value += 1
|
|
475
|
+
|
|
476
|
+
def start(self):
|
|
477
|
+
# Set all relevant os environment variables such libraries in the
|
|
478
|
+
# new process only use single-threaded computation.
|
|
479
|
+
with RequestSingleThreaded():
|
|
480
|
+
mp_spawn.Process.start(self)
|
|
@@ -10,6 +10,7 @@ import traceback
|
|
|
10
10
|
|
|
11
11
|
import numpy as np
|
|
12
12
|
|
|
13
|
+
from ..os_env_st import RequestSingleThreaded, confirm_single_threaded
|
|
13
14
|
from ..meta.ppid import kwargs_to_ppid, ppid_to_kwargs
|
|
14
15
|
from ..read import HDF5Data
|
|
15
16
|
|
|
@@ -325,6 +326,7 @@ class QueueEventExtractor:
|
|
|
325
326
|
|
|
326
327
|
def run(self):
|
|
327
328
|
"""Main loop of worker process"""
|
|
329
|
+
confirm_single_threaded()
|
|
328
330
|
self.worker_monitor[self.worker_index] = 0
|
|
329
331
|
# Don't wait for these two queues when joining workers
|
|
330
332
|
self.raw_queue.cancel_join_thread()
|
|
@@ -399,6 +401,12 @@ class EventExtractorProcess(QueueEventExtractor, mp_spawn.Process):
|
|
|
399
401
|
super(EventExtractorProcess, self).__init__(
|
|
400
402
|
name="EventExtractorProcess", *args, **kwargs)
|
|
401
403
|
|
|
404
|
+
def start(self):
|
|
405
|
+
# Set all relevant os environment variables such libraries in the
|
|
406
|
+
# new process only use single-threaded computation.
|
|
407
|
+
with RequestSingleThreaded():
|
|
408
|
+
mp_spawn.Process.start(self)
|
|
409
|
+
|
|
402
410
|
|
|
403
411
|
class EventExtractorThread(QueueEventExtractor, threading.Thread):
|
|
404
412
|
"""Threading worker for debugging (only one single thread)"""
|
dcnum/logic/ctrl.py
CHANGED
|
@@ -128,33 +128,6 @@ class DCNumJobRunner(threading.Thread):
|
|
|
128
128
|
|
|
129
129
|
self.logger = logging.getLogger(f"dcnum.Runner-{self.pphash[:2]}")
|
|
130
130
|
|
|
131
|
-
# Sanity checks
|
|
132
|
-
for os_env in ["MKL_NUM_THREADS", "NUMBA_NUM_THREADS",
|
|
133
|
-
"NUMEXPR_NUM_THREADS", "NUMPY_NUM_THREADS",
|
|
134
|
-
"OPENBLAS_NUM_THREADS", "OMP_NUM_THREADS",
|
|
135
|
-
"VECLIB_MAXIMUM_THREADS"]:
|
|
136
|
-
# You should disable multithreading for all major tools that
|
|
137
|
-
# use dcnum.logic. We don't want multithreading, because dcnum
|
|
138
|
-
# uses linear code and relies on multiprocessing for
|
|
139
|
-
# parallelization. This has to be done before importing numpy
|
|
140
|
-
# or any other library affected. In your scripts, you can use:
|
|
141
|
-
#
|
|
142
|
-
# os.environ.setdefault("MKL_NUM_THREADS", "1")
|
|
143
|
-
# os.environ.setdefault("NUMBA_NUM_THREADS", "1")
|
|
144
|
-
# os.environ.setdefault("NUMEXPR_NUM_THREADS", "1")
|
|
145
|
-
# os.environ.setdefault("NUMPY_NUM_THREADS", "1")
|
|
146
|
-
# os.environ.setdefault("OPENBLAS_NUM_THREADS", "1")
|
|
147
|
-
# os.environ.setdefault("OMP_NUM_THREADS", "1")
|
|
148
|
-
# os.environ.setdefault("VECLIB_MAXIMUM_THREADS", "1")
|
|
149
|
-
#
|
|
150
|
-
val_act = os.environ.get(os_env)
|
|
151
|
-
if val_act != "1":
|
|
152
|
-
self.logger.warning(
|
|
153
|
-
f"Make sure to set the environment variable {os_env} to "
|
|
154
|
-
f"'1' (disables multithreading)! Other values will reduce "
|
|
155
|
-
f"performance and your system may become inresponsive. "
|
|
156
|
-
f"The current value is '{val_act}'.")
|
|
157
|
-
|
|
158
131
|
def __enter__(self):
|
|
159
132
|
return self
|
|
160
133
|
|
dcnum/os_env_st.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
logger = logging.getLogger(__name__)
|
|
6
|
+
|
|
7
|
+
#: environment variables that set number of threads
|
|
8
|
+
os_env_threading = [
|
|
9
|
+
"MKL_NUM_THREADS",
|
|
10
|
+
"NUMBA_NUM_THREADS",
|
|
11
|
+
"NUMEXPR_NUM_THREADS",
|
|
12
|
+
"NUMPY_NUM_THREADS",
|
|
13
|
+
"OMP_NUM_THREADS",
|
|
14
|
+
"OPENBLAS_NUM_THREADS",
|
|
15
|
+
"VECLIB_MAXIMUM_THREADS",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class RequestSingleThreaded:
|
|
20
|
+
"""Context manager for starting a process with specific environment
|
|
21
|
+
|
|
22
|
+
When entering the context, the environment variables defined in
|
|
23
|
+
`os_env_threading` are all set to "1", telling the relevant libraries
|
|
24
|
+
that they should work in single-threaded mode.
|
|
25
|
+
When exiting the context, these environment variables are reset to
|
|
26
|
+
their original values (or unset if applicable).
|
|
27
|
+
|
|
28
|
+
Note that it makes only sense to use this context manager when
|
|
29
|
+
starting new multiprocessing processes. When the process spawns,
|
|
30
|
+
the environment from the current thread is copied. Setting the
|
|
31
|
+
environment variable after e.g. importing numpy has no effect
|
|
32
|
+
on how many threads numpy will use.
|
|
33
|
+
"""
|
|
34
|
+
def __init__(self):
|
|
35
|
+
self.previous_env = {}
|
|
36
|
+
|
|
37
|
+
def __enter__(self):
|
|
38
|
+
"""Ask nicely for single-threaded computation using `os.environ`
|
|
39
|
+
|
|
40
|
+
Note that this only affects new processes in which the
|
|
41
|
+
relevant libraries have not yet been imported.
|
|
42
|
+
"""
|
|
43
|
+
for key in os_env_threading:
|
|
44
|
+
if key in os.environ:
|
|
45
|
+
self.previous_env[key] = os.environ[key]
|
|
46
|
+
os.environ[key] = "1"
|
|
47
|
+
return self
|
|
48
|
+
|
|
49
|
+
def __exit__(self, type, value, traceback):
|
|
50
|
+
"""Restore the previous environment"""
|
|
51
|
+
for key in os_env_threading:
|
|
52
|
+
if key not in self.previous_env:
|
|
53
|
+
os.environ.pop(key)
|
|
54
|
+
else:
|
|
55
|
+
os.environ[key] = self.previous_env[key]
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def confirm_single_threaded():
|
|
59
|
+
"""Warn via logs when environment variables are not set to single thread"""
|
|
60
|
+
# Sanity checks
|
|
61
|
+
for os_env in os_env_threading:
|
|
62
|
+
# You should disable multithreading for all major tools that
|
|
63
|
+
# use dcnum.logic. We don't want multithreading, because dcnum
|
|
64
|
+
# uses linear code and relies on multiprocessing for
|
|
65
|
+
# parallelization. This has to be done before importing numpy
|
|
66
|
+
# or any other library affected. In your scripts, you can use:
|
|
67
|
+
#
|
|
68
|
+
val_act = os.environ.get(os_env)
|
|
69
|
+
if val_act != "1":
|
|
70
|
+
logger.warning(
|
|
71
|
+
f"Make sure to set the environment variable {os_env} to "
|
|
72
|
+
f"'1' (disables multithreading)! Other values will reduce "
|
|
73
|
+
f"performance and your system may become unresponsive. "
|
|
74
|
+
f"The current value is '{val_act}'.")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def request_single_threaded():
|
|
78
|
+
"""Set the environment variable to single thread
|
|
79
|
+
|
|
80
|
+
This function must be called before importing the multithreaded
|
|
81
|
+
libraries (such as numpy) in order for them to pick up the
|
|
82
|
+
environment variables.
|
|
83
|
+
"""
|
|
84
|
+
for key in os_env_threading:
|
|
85
|
+
os.environ[key] = "1"
|
dcnum/read/hdf5_data.py
CHANGED
|
@@ -593,8 +593,11 @@ def concatenated_hdf5_data(paths: List[pathlib.Path],
|
|
|
593
593
|
raise ValueError(
|
|
594
594
|
f"Invalid type for `path_out`: {type(path_out)} ({path_out}")
|
|
595
595
|
|
|
596
|
-
if len(paths)
|
|
597
|
-
raise ValueError("Please specify at least
|
|
596
|
+
if len(paths) == 0:
|
|
597
|
+
raise ValueError("Please specify at least one file in `paths`!")
|
|
598
|
+
elif len(paths) == 1:
|
|
599
|
+
warnings.warn("Only one file passed to `concatenated_hdf5_data`; this "
|
|
600
|
+
"is equivalent to using `HDF5Data`, but slower.")
|
|
598
601
|
|
|
599
602
|
frames = []
|
|
600
603
|
|
dcnum/segm/segmenter_mpo.py
CHANGED
|
@@ -7,6 +7,8 @@ from typing import Dict
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
import scipy.ndimage as ndi
|
|
9
9
|
|
|
10
|
+
from ..os_env_st import RequestSingleThreaded, confirm_single_threaded
|
|
11
|
+
|
|
10
12
|
from .segmenter import Segmenter
|
|
11
13
|
|
|
12
14
|
|
|
@@ -325,7 +327,8 @@ class MPOSegmenterWorker:
|
|
|
325
327
|
self.sl_stop = sl_stop
|
|
326
328
|
|
|
327
329
|
def run(self):
|
|
328
|
-
#
|
|
330
|
+
# confirm single-threadedness (prints to log)
|
|
331
|
+
confirm_single_threaded()
|
|
329
332
|
# We have to create the numpy-versions of the mp.RawArrays here,
|
|
330
333
|
# otherwise we only get some kind of copy in the new process
|
|
331
334
|
# when we use "spawn" instead of "fork".
|
|
@@ -369,6 +372,12 @@ class MPOSegmenterWorkerProcess(MPOSegmenterWorker, mp_spawn.Process):
|
|
|
369
372
|
def __init__(self, *args, **kwargs):
|
|
370
373
|
super(MPOSegmenterWorkerProcess, self).__init__(*args, **kwargs)
|
|
371
374
|
|
|
375
|
+
def start(self):
|
|
376
|
+
# Set all relevant os environment variables such libraries in the
|
|
377
|
+
# new process only use single-threaded computation.
|
|
378
|
+
with RequestSingleThreaded():
|
|
379
|
+
mp_spawn.Process.start(self)
|
|
380
|
+
|
|
372
381
|
|
|
373
382
|
class MPOSegmenterWorkerThread(MPOSegmenterWorker, threading.Thread):
|
|
374
383
|
def __init__(self, *args, **kwargs):
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
dcnum/__init__.py,sha256=hcawIKS7utYiOyVhOAX9t7K3xYzP1b9862VV0b6qSrQ,74
|
|
2
|
-
dcnum/_version.py,sha256=
|
|
2
|
+
dcnum/_version.py,sha256=2KpEHoGK3-a2p8saB4NXVEuWwhXBRfqcz_ebPkLNw7A,413
|
|
3
|
+
dcnum/os_env_st.py,sha256=ujEVzn1G5sxZfJSITOMw48e2O_oMFu2VD6oj5QCUFSU,3025
|
|
3
4
|
dcnum/feat/__init__.py,sha256=jUJYWTD3VIoDNKrmryXbjHb1rGwYtK4b7VPWihYgUoo,325
|
|
4
5
|
dcnum/feat/event_extractor_manager_thread.py,sha256=FAxSyRfaNAuBWNplxHngp5h-44s0qIP24XX_oETdfMk,7836
|
|
5
6
|
dcnum/feat/gate.py,sha256=Yhxq80JoRMmQzBxl35C8NT91c9QcmQa-EIKLuxK6WvE,7221
|
|
6
|
-
dcnum/feat/queue_event_extractor.py,sha256=
|
|
7
|
+
dcnum/feat/queue_event_extractor.py,sha256=KA7K7fOUbLYRfHjdfmN6mVuPPjCJbWMCHv0-b41lBMs,16038
|
|
7
8
|
dcnum/feat/feat_background/__init__.py,sha256=OTmMuazHNaSrZb2XW4cnJ6PlgJLbKrPbaidpEixYa0A,341
|
|
8
9
|
dcnum/feat/feat_background/base.py,sha256=bQBPvztrku-8YSVk8YBUUNh7MaYcnztgyD2-dQHxpzw,8674
|
|
9
10
|
dcnum/feat/feat_background/bg_copy.py,sha256=PK8x4_Uph-_A6uszZC5uhe1gD1dSRdHnDMEsN0HSGHA,1034
|
|
10
|
-
dcnum/feat/feat_background/bg_roll_median.py,sha256=
|
|
11
|
-
dcnum/feat/feat_background/bg_sparse_median.py,sha256=
|
|
11
|
+
dcnum/feat/feat_background/bg_roll_median.py,sha256=NqdgVYm-iUhgDZEonZxQrDvh5e26NoryQKCge8pNGoM,13571
|
|
12
|
+
dcnum/feat/feat_background/bg_sparse_median.py,sha256=QrerkPENHkC9PBgivamu-N1Od6-0b61Ohy_oZYL4www,22449
|
|
12
13
|
dcnum/feat/feat_brightness/__init__.py,sha256=o6AebVlmydwNgVF5kW6ITqJyFreoKrU3Ki_3EC8If-s,155
|
|
13
14
|
dcnum/feat/feat_brightness/bright_all.py,sha256=vf8xaYBdKD24hHUXdkI0_S7nbr7m49KW6gvuWvbHDVg,4545
|
|
14
15
|
dcnum/feat/feat_brightness/common.py,sha256=JX49EszYDmnvoOKXFVV1CalEIWRmOuY5EryNbqGbdac,156
|
|
@@ -20,7 +21,7 @@ dcnum/feat/feat_texture/__init__.py,sha256=6StM9S540UVtdFFR3bHa7nfCTomeVdoo7Uy9C
|
|
|
20
21
|
dcnum/feat/feat_texture/common.py,sha256=COXHpXS-7DMouGu3WF83I76L02Sr7P9re4lxajh6g0E,439
|
|
21
22
|
dcnum/feat/feat_texture/tex_all.py,sha256=_5H3sXYRN0Uq2eUHn3XUyEHkU_tncEqbqJTC-HZcnGY,5198
|
|
22
23
|
dcnum/logic/__init__.py,sha256=7J3GrwJInNQbrLk61HRIV7X7p69TAIbMYpR34hh6u14,177
|
|
23
|
-
dcnum/logic/ctrl.py,sha256=
|
|
24
|
+
dcnum/logic/ctrl.py,sha256=RZ2xl0496Iv91cdCdbkIg2W1fClqsTUDq7YlHHwWQfk,37514
|
|
24
25
|
dcnum/logic/job.py,sha256=9BN2WjYqjjJuLnfNZAtQ2Nn47Glo2jVrivDodGJoqlQ,7713
|
|
25
26
|
dcnum/logic/json_encoder.py,sha256=cxMnqisbKEVf-rVcw6rK2BBAb6iz_hKFaGl81kK36lQ,571
|
|
26
27
|
dcnum/meta/__init__.py,sha256=AVqRgyKXO1orKnE305h88IBvoZ1oz6X11HN1WP5nGvg,60
|
|
@@ -30,13 +31,13 @@ dcnum/read/__init__.py,sha256=LYHyZHgiNTpjV5oEcty-7Kh5topLpHT_cFlNl-QX8gg,262
|
|
|
30
31
|
dcnum/read/cache.py,sha256=LNA5nnDyrw8Nj07E7XfG2GcHEoWm6vA6Qo_8N-n-sGw,6492
|
|
31
32
|
dcnum/read/const.py,sha256=GG9iyXDtEldvJYOBnhZjlimzIeBMAt4bSr2-xn2gzzc,464
|
|
32
33
|
dcnum/read/detect_flicker.py,sha256=CeUyxI6LaX_lCNvBPm_yzsiWmiNcZYqbNZCtvKPdkcU,1827
|
|
33
|
-
dcnum/read/hdf5_data.py,sha256=
|
|
34
|
+
dcnum/read/hdf5_data.py,sha256=jo3LbwMqrr-qjoj8Fkv1eOdEE-ZZCZTjcGddzSx--MY,26044
|
|
34
35
|
dcnum/read/mapped.py,sha256=zU2fYdZfLNHn0rKHxDzBhNFMu4--WWa8nSeE2likyZA,3637
|
|
35
36
|
dcnum/segm/__init__.py,sha256=9cLEAd3JWE8IGqDHV-eSDIYOGBfOepd8OcebtNs8Omk,309
|
|
36
37
|
dcnum/segm/segm_thresh.py,sha256=iVhvIhzO0Gw0t3rXOgH71rOI0CNjJJQq4Gg6BulUhK8,948
|
|
37
38
|
dcnum/segm/segmenter.py,sha256=FWLFDBR-x_85ku2rObA2F-QBrM4IUaUL-YHChLagVvM,14902
|
|
38
39
|
dcnum/segm/segmenter_manager_thread.py,sha256=frM0sMxC7f7TQiFjmpRxuwG2kUBFpW1inV8dtpADHiI,5924
|
|
39
|
-
dcnum/segm/segmenter_mpo.py,sha256=
|
|
40
|
+
dcnum/segm/segmenter_mpo.py,sha256=XcYMKTnCu6-D-TJ62V18S3OE9DhaPhqFkhGhUaDWJFg,14096
|
|
40
41
|
dcnum/segm/segmenter_sto.py,sha256=e6MtN_RWusA0wTExV-FLGpDXNJs1CbSyXcSdWUPBMvM,3959
|
|
41
42
|
dcnum/segm/segm_torch/__init__.py,sha256=DtUqJTbj7ybrTbXlwHq1Y4SCzi22rMW9Cus6wX-iU-A,822
|
|
42
43
|
dcnum/segm/segm_torch/segm_torch_base.py,sha256=G9AhVyD6LkAmk0tkbYnJUSpvcj3_HYf0uqfILZQsyus,4479
|
|
@@ -49,8 +50,8 @@ dcnum/write/__init__.py,sha256=sK79IlvCFIqf2oFABVeyYedMnHOsEIQpxAauEeNO-Tw,273
|
|
|
49
50
|
dcnum/write/deque_writer_thread.py,sha256=ao7F1yrVKyufgC4rC0Y2_Vt7snuT6KpI7W2qVxcjdhk,1994
|
|
50
51
|
dcnum/write/queue_collector_thread.py,sha256=KwwNIDFEF2DU83woKES5K05MxxOhDxPMZLLeyPugfDo,11542
|
|
51
52
|
dcnum/write/writer.py,sha256=oHlq4bDHQxb33-3Fw1xnzJwACecLyH-6koGK8SN0cSk,20528
|
|
52
|
-
dcnum-0.25.
|
|
53
|
-
dcnum-0.25.
|
|
54
|
-
dcnum-0.25.
|
|
55
|
-
dcnum-0.25.
|
|
56
|
-
dcnum-0.25.
|
|
53
|
+
dcnum-0.25.4.dist-info/LICENSE,sha256=YRChA1C8A2E-amJbudwMcbTCZy_HzmeY0hMIvduh1MM,1089
|
|
54
|
+
dcnum-0.25.4.dist-info/METADATA,sha256=uqKK3Br_6ILIASamWdczQsgdqKG8rJcOwCAV_1JEN78,2326
|
|
55
|
+
dcnum-0.25.4.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
|
|
56
|
+
dcnum-0.25.4.dist-info/top_level.txt,sha256=Hmh38rgG_MFTVDpUDGuO2HWTSq80P585Het4COQzFTg,6
|
|
57
|
+
dcnum-0.25.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|