cubevis 1.0.14__py3-none-any.whl → 1.0.26__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.
cubevis/utils/_jupyter.py CHANGED
@@ -1,3 +1,5 @@
1
+ import os
2
+ import sys
1
3
  import logging
2
4
 
3
5
  logger = logging.getLogger(__name__)
@@ -17,6 +19,15 @@ logger = logging.getLogger(__name__)
17
19
  # except NameError:
18
20
  # return False
19
21
 
22
+ def is_colab():
23
+ """
24
+ Detects if the current environment is Google Colab.
25
+ Combines module check (process-level) and env-var check (VM-level).
26
+ """
27
+ # 1. Check for the Colab-specific environment variable (VM level)
28
+ # 2. Check for the google.colab module (Python process level)
29
+ return os.getenv("COLAB_RELEASE_TAG") is not None or 'google.colab' in sys.modules
30
+
20
31
  def is_interactive_jupyter( ) -> bool:
21
32
  """
22
33
  Detect if running in an interactive Jupyter notebook with frontend connection.
@@ -25,6 +36,7 @@ def is_interactive_jupyter( ) -> bool:
25
36
  - Interactive Jupyter notebook/lab with frontend (returns True)
26
37
  - Standalone Jupyter kernel without frontend (returns False)
27
38
  - Regular Python interpreter (returns False)
39
+ - Support Google Colab and legacy Jupyter versions.
28
40
 
29
41
  Returns:
30
42
  bool: True if running in interactive Jupyter with frontend, False otherwise
@@ -37,12 +49,21 @@ def is_interactive_jupyter( ) -> bool:
37
49
  logger.debug(f"\tis_interactive_jupyter<1>: False")
38
50
  return False
39
51
 
40
- # Check if we're in a ZMQ-based shell (kernel)
41
- if ipython.__class__.__name__ != 'ZMQInteractiveShell':
52
+ # Allow Colab's 'Shell' class in addition to standard 'ZMQInteractiveShell'
53
+ shell_class = ipython.__class__.__name__
54
+ is_colab = 'google.colab' in sys.modules
55
+
56
+ # Check if we're in a ZMQ-based shell (kernel) or Colab's 'Shell'
57
+ if shell_class not in ['ZMQInteractiveShell', 'Shell'] and not is_colab:
42
58
  logger.debug(f"\tis_interactive_jupyter<2>: False")
43
59
  return False
44
60
 
45
- # Check for active frontend connection
61
+ # If we are in Colab, the existence of the shell itself implies
62
+ # an interactive frontend, as Colab sessions are inherently interactive.
63
+ if is_colab:
64
+ return True
65
+
66
+ # Check for active frontend connection (Standard Jupyter/Legacy)
46
67
  if hasattr(ipython, 'kernel') and ipython.kernel is not None:
47
68
  kernel = ipython.kernel
48
69
 
@@ -51,14 +72,15 @@ def is_interactive_jupyter( ) -> bool:
51
72
  # For newer Jupyter versions, check connection count
52
73
  if hasattr(kernel, 'connection_count'):
53
74
  logger.debug(f"\tis_interactive_jupyter<3>: {kernel.connection_count > 0}")
54
- return kernel.connection_count > 0
75
+ if kernel.connection_count > 0:
76
+ return True
55
77
 
56
78
  # For older versions, check if socket is connected
57
79
  try:
58
80
  # Try to get socket state - if it fails, likely no frontend
59
- socket_state = kernel.shell_socket.closed
60
81
  logger.debug(f"\tis_interactive_jupyter<4>: {not socket_state}")
61
- return not socket_state
82
+ if not kernel.shell_socket.closed:
83
+ return True
62
84
  except AttributeError:
63
85
  pass
64
86
 
@@ -68,7 +90,8 @@ def is_interactive_jupyter( ) -> bool:
68
90
  parent = kernel.get_parent()
69
91
  # If there's a parent message, we're likely in interactive mode
70
92
  logger.debug(f"\tis_interactive_jupyter<5>: {parent is not None and len(parent) > 0}")
71
- return parent is not None and len(parent) > 0
93
+ if parent is not None and len(parent) > 0:
94
+ return True
72
95
  except Exception:
73
96
  pass
74
97
 
@@ -77,12 +100,12 @@ def is_interactive_jupyter( ) -> bool:
77
100
  logger.debug(f"\tis_interactive_jupyter<6>: True")
78
101
  return True
79
102
 
80
- # Fallback: Check for common Jupyter notebook environment indicators
81
- # This catches cases where kernel introspection doesn't work
82
- import os
103
+ # Fallback: Check for environment indicators (Legacy/Containerized Jupyter)
83
104
  jupyter_indicators = [
84
- 'JPY_PARENT_PID', # JupyterLab/Notebook sets this
105
+ 'JPY_PARENT_PID', # JupyterLab/Notebook sets this
85
106
  'JUPYTER_RUNTIME_DIR',
107
+ 'COLAB_RELEASE_DEVICE', # Additional Colab-specific env check
108
+ 'COLAB_GPU' # Additional Colab-specific env check
86
109
  ]
87
110
 
88
111
  for indicator in jupyter_indicators:
@@ -99,6 +122,6 @@ def is_interactive_jupyter( ) -> bool:
99
122
  logger.debug(f"\tis_interactive_jupyter<8>: False")
100
123
  return False
101
124
 
102
- except ImportError:
125
+ except (ImportError, Exception):
103
126
  logger.debug(f"\tis_interactive_jupyter<9>: False")
104
127
  return False
@@ -0,0 +1,117 @@
1
+ import threading
2
+ from typing import Dict
3
+
4
+
5
+ class MutualExclusionManager:
6
+ """
7
+ Generic manager for enforcing mutual exclusion between different execution paths.
8
+
9
+ Use this when you want to ensure only one of several mutually exclusive paths
10
+ can be taken within a given context (thread).
11
+
12
+ Example:
13
+ mode_manager = MutualExclusionManager(
14
+ name="display_mode",
15
+ valid_modes={
16
+ 'notebook': "Cannot use Showable after displaying with bokeh.plotting.show().",
17
+ 'separate_tab': "Cannot use bokeh.plotting.show() after displaying with Showable."
18
+ }
19
+ )
20
+
21
+ # In path A:
22
+ mode_manager.set_mode('notebook')
23
+
24
+ # In path B (will raise error if path A was already taken):
25
+ mode_manager.set_mode('separate_tab')
26
+ """
27
+
28
+ def __init__(self, name: str, valid_modes: Dict[str, str]):
29
+ """
30
+ Args:
31
+ name: Descriptive name for this manager (used in error messages)
32
+ valid_modes: Dictionary mapping mode names to error messages to display
33
+ when that mode conflicts with an already-set mode.
34
+ """
35
+ self.name = name
36
+ self.valid_modes = valid_modes
37
+ self._local = threading.local()
38
+
39
+ def set_mode(self, mode: str):
40
+ """
41
+ Set the execution mode. Raises RuntimeError if a different mode was already set.
42
+
43
+ Args:
44
+ mode: The mode identifier to set
45
+
46
+ Raises:
47
+ ValueError: If mode is not in valid_modes
48
+ RuntimeError: If a different mode was already set in this context
49
+ """
50
+ if mode not in self.valid_modes:
51
+ raise ValueError(
52
+ f"Invalid mode '{mode}' for {self.name}. "
53
+ f"Valid modes: {set(self.valid_modes.keys())}"
54
+ )
55
+
56
+ current_mode = self.get_mode()
57
+ if current_mode is not None and current_mode != mode:
58
+ # Use the error message associated with the mode being set
59
+ error_message = self.valid_modes[mode]
60
+ raise RuntimeError(error_message)
61
+
62
+ self._local.mode = mode
63
+
64
+ def get_mode(self) -> str | None:
65
+ """
66
+ Get the current mode, or None if no mode has been set.
67
+
68
+ Returns:
69
+ The current mode string, or None
70
+ """
71
+ return getattr(self._local, 'mode', None)
72
+
73
+ def require_mode(self, mode: str):
74
+ """
75
+ Check that we're in the specified mode, set it if unset, error if different.
76
+
77
+ This is a convenience method that combines get_mode checking with set_mode.
78
+
79
+ Args:
80
+ mode: The required mode
81
+
82
+ Raises:
83
+ RuntimeError: If a different mode was already set
84
+ """
85
+ self.set_mode(mode)
86
+
87
+ def forbid_mode(self, mode: str, message: str | None = None):
88
+ """
89
+ Raise an error if the current mode matches the specified mode.
90
+
91
+ Args:
92
+ mode: The mode to forbid
93
+ message: Optional custom error message. If None, uses the message from valid_modes.
94
+
95
+ Raises:
96
+ RuntimeError: If current mode matches the forbidden mode
97
+ """
98
+ current_mode = self.get_mode()
99
+ if current_mode == mode:
100
+ if message is None:
101
+ message = self.valid_modes.get(
102
+ mode,
103
+ f"Cannot proceed: {self.name} is set to '{mode}', "
104
+ f"which is not allowed in this context."
105
+ )
106
+ raise RuntimeError(message)
107
+
108
+ def reset(self):
109
+ """
110
+ Reset the mode for this context. Useful for testing or manual mode switching.
111
+ """
112
+ if hasattr(self._local, 'mode'):
113
+ del self._local.mode
114
+
115
+ def __repr__(self):
116
+ mode = self.get_mode()
117
+ return f"MutualExclusionManager(name='{self.name}', current_mode={mode!r})"
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cubevis
3
- Version: 1.0.14
3
+ Version: 1.0.26
4
4
  Summary: visualization toolkit and apps for casa
5
5
  License: LGPL
6
6
  Author-email: Darrell Schiebel <darrell@schiebel.us>,Pam Harris <pharris@nrao.edu>
7
7
  Requires-Python: >=3.11
8
8
  Requires-Dist: astropy>=5.1
9
- Requires-Dist: bokeh<3.9,>=3.8
9
+ Requires-Dist: bokeh<3.9,>=3.6
10
10
  Requires-Dist: certifi
11
11
  Requires-Dist: matplotlib
12
12
  Requires-Dist: regions>=0.8
@@ -30,11 +30,11 @@ cubevis/__icons__/trash_full_raw.png,sha256=8ChZlNOqnDqmNhNYoqyLiGluYwJSYeQ2UvNL
30
30
  cubevis/__icons__/zoom-to-fit.png,sha256=aozGbrkoBX1q9kV0p272bg0YKGje1gIfVBkFZRlLAXs,9592
31
31
  cubevis/__icons__/zoom-to-fit.svg,sha256=NtYorWvH4s68iAMriqCPGuTBX5SsgVN310UXGKDM7i8,1802
32
32
  cubevis/__init__.py,sha256=c_7j2VgZ9yeRJOoFlzzQt-bQ_awlBMaaPJPSB0MNfcg,3233
33
- cubevis/__js__/bokeh-3.6/cubevisjs.min.js,sha256=F7HjEMjJpJOCCPIuydjOnv4oU1LNjHUJdsho8ZXbTnE,32149
34
- cubevis/__js__/bokeh-3.7/cubevisjs.min.js,sha256=pZ6xsZwdiVQ_oQiFN7N9sJDUCwHQy4KekPE5ycuFgn4,31088
35
- cubevis/__js__/bokeh-3.8/cubevisjs.min.js,sha256=KYALPxQSmcSUSbzlQwd7-2FE2TYbKbPY-mp2GgmFPac,35629
33
+ cubevis/__js__/bokeh-3.6/cubevisjs.min.js,sha256=bZ8IjciHZwcUMrrc_6a3n965WlPCMeQedZjb4-0Ln34,42526
34
+ cubevis/__js__/bokeh-3.7/cubevisjs.min.js,sha256=bZ8IjciHZwcUMrrc_6a3n965WlPCMeQedZjb4-0Ln34,42526
35
+ cubevis/__js__/bokeh-3.8/cubevisjs.min.js,sha256=bZ8IjciHZwcUMrrc_6a3n965WlPCMeQedZjb4-0Ln34,42526
36
36
  cubevis/__js__/casalib.min.js,sha256=J9Uvlat_Vf6cjcvftOG5COk3YH6A371MJ7s5u_ZS2_4,91133
37
- cubevis/bokeh/__init__.py,sha256=b2Vgszi7sQPFyu2b4fnQzVXk5uX4B9vb59CilQpP31I,1835
37
+ cubevis/bokeh/__init__.py,sha256=dDIV8jBZji-bD8TQQKBMaF5UuabaJ5NICWn6g_QHxvs,1885
38
38
  cubevis/bokeh/annotations/__init__.py,sha256=tjDIPKbg-rh7Iu3coFWvmX-j2yNj9KuKmRp1aTo71ww,50
39
39
  cubevis/bokeh/annotations/_ev_poly_annotation.py,sha256=RzP4E1_rII9z37uHX2nUnXhzfPSvw0noYpcjE7M0YCk,208
40
40
  cubevis/bokeh/components/__init__.py,sha256=BQOqgBtlDpu6ENrY42nYeS73n2ZSMogJgM2LtJibfVM,1314
@@ -42,11 +42,11 @@ cubevis/bokeh/format/__init__.py,sha256=umNotXSRR23675c44x3h5h2ILbZX8xrDFCztvriY
42
42
  cubevis/bokeh/format/_time_ticks.py,sha256=j-DcPh7RfGE8iX2bPjLQDQPIbiAbmjiEWQnKmdMWA3I,1773
43
43
  cubevis/bokeh/format/_wcs_ticks.py,sha256=RtonOEc-QXzUNmwg3Ec9ONM5u1Sq8_x5CmRdUwQi5HA,2079
44
44
  cubevis/bokeh/models/__init__.py,sha256=3ICcAlkQXMvuAblh8wfcAA5aJFT2z_QN249pEITMR40,247
45
- cubevis/bokeh/models/_bokeh_app_context.py,sha256=ScF1mSkTnxOJj2NwWWHO_UtDZMx4CH2pF1vm64oYUWI,2209
45
+ cubevis/bokeh/models/_bokeh_app_context.py,sha256=iHCFAJzFinX8I6ty3Vdw6w0Za-5qpoPpSNvbIbc3Q7M,4142
46
46
  cubevis/bokeh/models/_edit_span.py,sha256=7o59ZS0bF_Q_WtstvViWXP-2PiY_F7_zCecTqKcmz0E,196
47
47
  cubevis/bokeh/models/_ev_text_input.py,sha256=SGtefXkWK6jHEk4EneZ_hEUGwoIWwVGjwqLjGsAXMpY,158
48
48
  cubevis/bokeh/models/_shared_dict.py,sha256=AWjLMOKVAXWHSF4gcK2RbxF442QlzQ7hMR0oaODCqB0,901
49
- cubevis/bokeh/models/_showable.py,sha256=7_2qO2EGRk6iEy44AJv_KL5ff0UvDzOahgM6K8q0Nrs,14368
49
+ cubevis/bokeh/models/_showable.py,sha256=uzLf8hhITweJnBB5Sm-XjLb1H-RGYfrSSuWVI1UekUc,18474
50
50
  cubevis/bokeh/models/_tip.py,sha256=yNoUWods0xxva1WOfh5It_Y8hbpVy8RVXUmm8p7a58M,1431
51
51
  cubevis/bokeh/models/_tip_button.py,sha256=mwk1C7BMVlZrAAyQLn45S4Q9GEQfU_wU2MWpO0Gwzj4,1610
52
52
  cubevis/bokeh/sources/__init__.py,sha256=4FsudFuVU4o7VG5OG3K1tiMoxIXcJWNz_K9yzMDE8ls,1581
@@ -57,7 +57,7 @@ cubevis/bokeh/sources/_spectra_data_source.py,sha256=qL1IOjSefWlycaqS4Pz5EHwg-1E
57
57
  cubevis/bokeh/sources/_updatable_data_source.py,sha256=Kib2DPPIA0abqOywzdme98GxI8KBukszbSC5K65wxv0,10961
58
58
  cubevis/bokeh/state/__init__.py,sha256=PZ2-7I5XHkMTc-vguYarYCYSJ1pKyEYnSAFa-n8AuTE,1826
59
59
  cubevis/bokeh/state/_current.py,sha256=owPMQTme5SBYvIVP3Q4y9hpWHPmyhLHsS2O0sCAAqqo,967
60
- cubevis/bokeh/state/_initialize.py,sha256=rdIP8wMHd3RtvnVNKbfpkybUl5ZLKqSyxUiOhq7a7Ss,12483
60
+ cubevis/bokeh/state/_initialize.py,sha256=eX06VU1KyTEyoFiAdPBA_XucCKFEgNImv1qVXfXaIkE,12881
61
61
  cubevis/bokeh/state/_javascript.py,sha256=0n-kVFOpmo11fuOhASh71JAttwOzm9T2vm8KC5m6h1Y,5390
62
62
  cubevis/bokeh/state/_palette.py,sha256=lPLgpKvc23mpNcaVu5nBAGdA_WBUK1HcxFJLu3CTvtg,2463
63
63
  cubevis/bokeh/state/_session.py,sha256=5TK6pyQOUPZNwnyjd_XmkqE_qPNkQyXIKjpFsliBvgk,1761
@@ -81,15 +81,15 @@ cubevis/exe/__init__.py,sha256=kH6dvUS_gjzlPxT1V-PU8ZCKvUTwIqJ-Es5UMfH9D9A,108
81
81
  cubevis/exe/_context.py,sha256=hcfn1YYXeIo8Jl_2HV0m2D2Qpo9z4qOunMJovThNctE,5676
82
82
  cubevis/exe/_mode.py,sha256=s7i19DY_BWESgqKdRQRnQaR5EK52rym4yu2eSylOHgA,139
83
83
  cubevis/exe/_setting.py,sha256=pND6qyQV69N5Y5pW7E8phesEAaGjDE45ASvUtlHPPUE,92
84
- cubevis/exe/_task.py,sha256=eslV_iUsDLaDqSkNLNEtzQg73FC9NJJLsPBss5TqFvA,10912
84
+ cubevis/exe/_task.py,sha256=L5w3wjOJmjrlzYtmNmX__uRugXgVb49CeeALwCEuzrU,11664
85
85
  cubevis/private/_gclean.py,sha256=ExdR6cRxSa6Xne2veGNKhbTtx-tXUIWr2htzEmEZ9Z4,41107
86
86
  cubevis/private/apps/__init__.py,sha256=eQg28HPmEskRVJDQviUyuXroBKpUxocaj0Snk-VBaW4,2927
87
- cubevis/private/apps/_createmask.py,sha256=kLwb138M3CyZWG2MIv0-1jdpxjpelmroY_85KlSJptA,23592
88
- cubevis/private/apps/_createregion.py,sha256=OHZzTUaQ8Ofl5xt2mCrhXEDkfED-B3TxL-TCi7EXVeo,26724
89
- cubevis/private/apps/_interactiveclean.mustache,sha256=fM6-8p1DrWcxNHx9YY1zQUn9trfvKqKekJAOHlLZ96o,3776
90
- cubevis/private/apps/_interactiveclean.py,sha256=QRPqR7uDQhrMz1FZ1E_OvWB6w1p9U0c4s33VMGCgff8,139277
91
- cubevis/private/apps/_interactivecleannotebook.mustache,sha256=TqWMC2rFHIhwsoz--d0RFaKAfPPbvU7wjlwuWHgRhpM,4494
92
- cubevis/private/apps/_interactivecleannotebook.py,sha256=0N65GJG4D9vKWnl1lMNpNuKotQpy8NePkB97cdc-uI8,139995
87
+ cubevis/private/apps/_createmask.py,sha256=MTsN47vuOu2iYjjQGHprnHWdJWTQea7clrTSG8TYtzY,23240
88
+ cubevis/private/apps/_createregion.py,sha256=Q5YmYOeh46WPN7xMite4OAUFpHSZtAFTvJD4R6bsjpY,27020
89
+ cubevis/private/apps/_interactiveclean.mustache,sha256=G8itL37DlLZU4Vxe24Sh6DM4aUFmoQSylALC1ktAiSg,3825
90
+ cubevis/private/apps/_interactiveclean.py,sha256=2N-FV8CcDyqVKpbktaaxIfP5RK2Dv71DWsDRxuUIan8,139326
91
+ cubevis/private/apps/_interactivecleannotebook.mustache,sha256=haJG7huuBCq8h9EwKaWQNsPEdOjTd5yLw9GUJxPr_jM,5251
92
+ cubevis/private/apps/_interactivecleannotebook.py,sha256=LJS9wRggRt2swJqWhDK3XRuS0ACGPGho5c5tjcm9-TI,140752
93
93
  cubevis/private/apps/_plotants.py,sha256=top6VWVd_sE48IVPH_sIg3_sQeDl5tadi5DL7r5tUEI,10823
94
94
  cubevis/private/apps/_plotbandpass.py,sha256=NwOgKSRnpLw9Pt3KIdBpoV78q1OnjCvj6lWFqeyICt8,185
95
95
  cubevis/private/casashell/createmask.py,sha256=C1eSUUsttSGghjZ5aDUVhRxnjir5MlYXVyxzEYLcI3k,14457
@@ -104,15 +104,15 @@ cubevis/remote/__init__.py,sha256=0LgSfWUw8cYnVrOYGq3o15tWJPkgcvTyYIrvRSAW6N8,12
104
104
  cubevis/remote/_gclean.py,sha256=TpmCmCUtMjqOFnA2wtYdp4EJo-59DyI00aaTWQbMQU4,1930
105
105
  cubevis/remote/_local.py,sha256=PcPCFcwttTFZd3O33-5pqDuGKQKK6CA0gz1MTIkTiNI,10326
106
106
  cubevis/remote/_remote_kernel.py,sha256=wfu7ZzKn-oCxZxzDIkC5puBvGf8WbCLYL3CzM56_FNc,2652
107
- cubevis/toolbox/__init__.py,sha256=xzqwAG9863d7UKBVBRw7FrRUQbvCdFcLBq4vTpg63DU,1487
107
+ cubevis/toolbox/__init__.py,sha256=sEN80BX91q_Z2zImDlT8oZ-0o8sE-iH7n3i4S1lmRLo,1450
108
108
  cubevis/toolbox/_app_context.py,sha256=rkjddiE4Ynf2HeyI0Hf8DOUt89bF67-2IlgD1uKSdOI,2908
109
- cubevis/toolbox/_cube.py,sha256=o-FSoq5giXbCVXdjDWWfEUGyvqV0Fw_QjP4EzHCmUZ8,306242
110
- cubevis/toolbox/_interactive_clean_ui.mustache,sha256=jDhATZohY14ntaG3N30E_gnf7uHkr4JwxXQmEYPwD4g,111937
111
- cubevis/toolbox/_interactive_clean_ui.py,sha256=N_TYgp8U-M6-A_5aNZaieIhwT-qhbkbPhc2ULaDuTDc,111848
109
+ cubevis/toolbox/_cube.py,sha256=ZqprhC7Ps9hGGcd3BLK3zp5wySy2QhnqyAXBkeMxtzY,308257
110
+ cubevis/toolbox/_interactive_clean_ui.mustache,sha256=IVTcqkxIyw7SzfU92_70dG7bF9UapromDdmeukQ90cg,114113
111
+ cubevis/toolbox/_interactive_clean_ui.py,sha256=98KnLZnDXqO5xl7Ie7WpirogtKL0a5myHejsC89CVSU,114024
112
112
  cubevis/toolbox/_interactiveclean_wrappers.py,sha256=XqyCGz33CMDhszTxnwZ_3-64GszUK1XYnGKUOxl9sas,5071
113
113
  cubevis/toolbox/_region_list.py,sha256=_1RvnXwqMoaAq8CPy-6IyhabLi_snXqO566onehI2y0,8957
114
114
  cubevis/utils/_ResourceManager.py,sha256=SaaR29etabRiKxmUK-aWvAm4v_OPFJH8CX7bNFm0Lgo,3410
115
- cubevis/utils/__init__.py,sha256=-hSFUv8F4DgpbtZY3uznn65cuMoqsYxvb17U9iC_E9Y,27994
115
+ cubevis/utils/__init__.py,sha256=Xd5GYSBw_hsONqJaXIwi1TZ0hJQ8WsjwWX6Q9V8S4AU,28058
116
116
  cubevis/utils/_browser.py,sha256=rmJ8_wq6XqhXZmVdmWI4t736qB-zd7ZbzfjVdVz40eY,261
117
117
  cubevis/utils/_contextmgrchain.py,sha256=r5SrCBdgQIVH7zXKOmq5oWhDUSeHaZpgsIfWFHvb3cQ,2859
118
118
  cubevis/utils/_conversion.py,sha256=SziCU8sOGtG7djlY766-MeOvnQgvT9C737FEfJ4aYsE,3262
@@ -120,14 +120,15 @@ cubevis/utils/_copydoc.py,sha256=SI9DOUoTNg9M-Y4J1oci2Ba1jebGHsx_pFX24RSNg3o,191
120
120
  cubevis/utils/_docenum.py,sha256=D79BvxwW18DPUlIhBx5DnpZh76pDURC1Hqt1DfS7kG0,877
121
121
  cubevis/utils/_git.py,sha256=fLrwN40zm6fv3SKz3MSwj-wtUa9AslpwPPIYJNLzXik,1120
122
122
  cubevis/utils/_import_protected_module.py,sha256=AIISHPdiSzwgVzLXqHSWSHT-L7lcMWbYrsMlGlTFafE,1482
123
- cubevis/utils/_jupyter.py,sha256=37aNCGO52sOyklBQAR5eaAHkv-5NpmzCXPuTT7Euk0o,4214
123
+ cubevis/utils/_jupyter.py,sha256=7itryScSkcej9ISvgItWaXhBRxCSaZagQYPvWYX_VAg,5256
124
124
  cubevis/utils/_logging.py,sha256=HqyoTib7QSuAUbzicPVMdhFtxWKo-Dv4GgD0AYDDXIY,2348
125
+ cubevis/utils/_mutual_exclusion.py,sha256=fkVsHPrFfeXdLSoZGw49ObxsTfwAeeJQTAcOCM2LvC8,3879
125
126
  cubevis/utils/_pkgs.py,sha256=mu2CCzndmJZYP81UkFhxveW_CisWLUvagJVolHOEVgM,2294
126
127
  cubevis/utils/_regions.py,sha256=TdAg4ZUUyhg3nFmX9_KLboqmc0LkyOdEW8M1WDR5Udk,1669
127
128
  cubevis/utils/_static.py,sha256=rN-sqXNqQ5R2M3wmPHU1GPP5OTyyWQlUPRuimCrht-g,2347
128
129
  cubevis/utils/_tiles.py,sha256=A9W1X61VOhBMTOKXVajzOIoiV2FBdO5N2SFB9SUpDOo,7336
129
- cubevis/__version__.py,sha256=3X90f6HGpDfnyIIIVOe0gXw8CJq4nN8scff1OJoFAmk,22
130
- cubevis-1.0.14.dist-info/WHEEL,sha256=B19PGBCYhWaz2p_UjAoRVh767nYQfk14Sn4TpIZ-nfU,87
131
- cubevis-1.0.14.dist-info/METADATA,sha256=Wu2Q1pdn4LY_7zwhqg8tbR7lVyTsJYOxKPvox9dIUQg,2632
132
- cubevis-1.0.14.dist-info/licenses/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
133
- cubevis-1.0.14.dist-info/RECORD,,
130
+ cubevis/__version__.py,sha256=ipKUrUZQTYULPss2w4_lq_zOzzw-qCGgjOtgkLfSDAM,22
131
+ cubevis-1.0.26.dist-info/WHEEL,sha256=B19PGBCYhWaz2p_UjAoRVh767nYQfk14Sn4TpIZ-nfU,87
132
+ cubevis-1.0.26.dist-info/METADATA,sha256=M-Nz1skw2jnDx84DLs5rY_tjgQdJHiZuJrNW3xmV9d0,2632
133
+ cubevis-1.0.26.dist-info/licenses/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
134
+ cubevis-1.0.26.dist-info/RECORD,,