batplot 1.8.1__py3-none-any.whl → 1.8.3__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 batplot might be problematic. Click here for more details.

Files changed (42) hide show
  1. batplot/__init__.py +1 -1
  2. batplot/args.py +2 -0
  3. batplot/batch.py +23 -0
  4. batplot/batplot.py +101 -12
  5. batplot/cpc_interactive.py +25 -3
  6. batplot/electrochem_interactive.py +20 -4
  7. batplot/interactive.py +19 -15
  8. batplot/modes.py +12 -12
  9. batplot/operando_ec_interactive.py +4 -4
  10. batplot/session.py +218 -0
  11. batplot/style.py +21 -2
  12. batplot/version_check.py +1 -1
  13. {batplot-1.8.1.dist-info → batplot-1.8.3.dist-info}/METADATA +1 -1
  14. batplot-1.8.3.dist-info/RECORD +75 -0
  15. {batplot-1.8.1.dist-info → batplot-1.8.3.dist-info}/top_level.txt +1 -0
  16. batplot_backup_20251221_101150/__init__.py +5 -0
  17. batplot_backup_20251221_101150/args.py +625 -0
  18. batplot_backup_20251221_101150/batch.py +1176 -0
  19. batplot_backup_20251221_101150/batplot.py +3589 -0
  20. batplot_backup_20251221_101150/cif.py +823 -0
  21. batplot_backup_20251221_101150/cli.py +149 -0
  22. batplot_backup_20251221_101150/color_utils.py +547 -0
  23. batplot_backup_20251221_101150/config.py +198 -0
  24. batplot_backup_20251221_101150/converters.py +204 -0
  25. batplot_backup_20251221_101150/cpc_interactive.py +4409 -0
  26. batplot_backup_20251221_101150/electrochem_interactive.py +4520 -0
  27. batplot_backup_20251221_101150/interactive.py +3894 -0
  28. batplot_backup_20251221_101150/manual.py +323 -0
  29. batplot_backup_20251221_101150/modes.py +799 -0
  30. batplot_backup_20251221_101150/operando.py +603 -0
  31. batplot_backup_20251221_101150/operando_ec_interactive.py +5487 -0
  32. batplot_backup_20251221_101150/plotting.py +228 -0
  33. batplot_backup_20251221_101150/readers.py +2607 -0
  34. batplot_backup_20251221_101150/session.py +2951 -0
  35. batplot_backup_20251221_101150/style.py +1441 -0
  36. batplot_backup_20251221_101150/ui.py +790 -0
  37. batplot_backup_20251221_101150/utils.py +1046 -0
  38. batplot_backup_20251221_101150/version_check.py +253 -0
  39. batplot-1.8.1.dist-info/RECORD +0 -52
  40. {batplot-1.8.1.dist-info → batplot-1.8.3.dist-info}/WHEEL +0 -0
  41. {batplot-1.8.1.dist-info → batplot-1.8.3.dist-info}/entry_points.txt +0 -0
  42. {batplot-1.8.1.dist-info → batplot-1.8.3.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,253 @@
1
+ """Version checking utility for batplot.
2
+
3
+ This module checks PyPI (Python Package Index) for newer versions of batplot
4
+ and notifies users when updates are available.
5
+
6
+ HOW VERSION CHECKING WORKS:
7
+ --------------------------
8
+ When you run batplot, it automatically (and silently) checks for updates:
9
+
10
+ 1. **Check Cache**: First checks a local cache file to see if we've checked recently
11
+ - Cache is valid for 1 hour (3600 seconds)
12
+ - If cache is fresh, use cached result (no network request)
13
+
14
+ 2. **Fetch from PyPI**: If cache is stale or missing:
15
+ - Makes HTTP request to PyPI API (https://pypi.org/pypi/batplot/json)
16
+ - Gets latest version number
17
+ - Updates cache with new version and timestamp
18
+
19
+ 3. **Compare Versions**: Compares current version vs latest version
20
+ - If latest > current: Show update notification
21
+ - If latest <= current: Do nothing (you're up to date)
22
+
23
+ 4. **Show Notification**: If update available, prints a friendly message
24
+ - Shows current and latest version numbers
25
+ - Provides update command: `pip install --upgrade batplot`
26
+ - Can be disabled with environment variable
27
+
28
+ DESIGN PRINCIPLES:
29
+ -----------------
30
+ - **Non-blocking**: 2 second timeout (won't slow down startup)
31
+ - **Cached**: Only checks once per hour (saves network requests)
32
+ - **Silent failure**: If check fails, program continues normally
33
+ - **Optional**: Can be disabled with BATPLOT_NO_VERSION_CHECK=1
34
+ - **User-friendly**: Clear, colored notification message
35
+
36
+ WHY CACHE?
37
+ ---------
38
+ Checking PyPI on every run would:
39
+ - Slow down startup (network latency)
40
+ - Waste bandwidth (unnecessary requests)
41
+ - Annoy PyPI servers (too many requests)
42
+
43
+ Caching for 1 hour means:
44
+ - Fast startup (no network request if cache is fresh)
45
+ - Still timely (checks once per hour, not once per day)
46
+ - Respectful to PyPI (fewer requests)
47
+ """
48
+
49
+ import os
50
+ import sys
51
+ import json
52
+ import time
53
+ from pathlib import Path
54
+ from typing import Optional, Tuple
55
+
56
+ # ====================================================================================
57
+ # UPDATE INFO CONFIGURATION
58
+ # ====================================================================================
59
+ # Edit this section to customize update notification messages and add update info.
60
+ #
61
+ # HOW TO USE:
62
+ # ----------
63
+ # When releasing a new version, edit the UPDATE_INFO dictionary below to include
64
+ # information about what's new or important in the update. This information will
65
+ # be displayed to users when they run batplot and a newer version is available.
66
+ #
67
+ # EXAMPLE:
68
+ # --------
69
+ # UPDATE_INFO = {
70
+ # 'custom_message': "This update includes important bug fixes and new features.",
71
+ # 'update_notes': [
72
+ # "- Fixed colormap preservation issue in session files",
73
+ # "- Improved legend positioning when toggling visibility",
74
+ # "- Added superscript/subscript shortcuts for labels",
75
+ # "- Enhanced version check notifications"
76
+ # ],
77
+ # 'show_update_notes': True,
78
+ # }
79
+ #
80
+ # To disable custom messages, set 'custom_message' to None.
81
+ # To disable update notes, set 'update_notes' to None or an empty list [].
82
+ # ====================================================================================
83
+
84
+ UPDATE_INFO = {
85
+ # Custom message to include in update notification
86
+ # Set to None or empty string to disable
87
+ # This will be displayed as an additional line in the update message box
88
+ 'custom_message': "This update includes important bug fixes", # Example: "This update includes important bug fixes."
89
+
90
+ # Additional notes about the update (list of strings)
91
+ # Set to None or empty list [] to disable
92
+ # Each item in the list will be displayed as a separate line
93
+ 'update_notes': None, # Example: ["- Fixed colormap preservation issue", "- Improved legend positioning"]
94
+
95
+ # Whether to show update notes if provided
96
+ # Set to False to hide update notes even if they are defined
97
+ 'show_update_notes': True,
98
+ }
99
+
100
+ # ====================================================================================
101
+ # END OF UPDATE INFO CONFIGURATION
102
+ # ====================================================================================
103
+
104
+
105
+ def get_cache_file() -> Path:
106
+ """Get the path to the version check cache file."""
107
+ # Use user's cache directory
108
+ if sys.platform == 'win32':
109
+ cache_dir = Path(os.environ.get('LOCALAPPDATA', Path.home() / 'AppData' / 'Local')) / 'batplot'
110
+ elif sys.platform == 'darwin':
111
+ cache_dir = Path.home() / 'Library' / 'Caches' / 'batplot'
112
+ else: # Linux and other Unix-like
113
+ cache_dir = Path(os.environ.get('XDG_CACHE_HOME', Path.home() / '.cache')) / 'batplot'
114
+
115
+ cache_dir.mkdir(parents=True, exist_ok=True)
116
+ return cache_dir / 'version_check.json'
117
+
118
+
119
+ def get_latest_version() -> Optional[str]:
120
+ """Fetch the latest version from PyPI.
121
+
122
+ Returns:
123
+ Latest version string, or None if check fails
124
+ """
125
+ try:
126
+ import urllib.request
127
+ import urllib.error
128
+
129
+ # Set a short timeout to avoid blocking
130
+ url = "https://pypi.org/pypi/batplot/json"
131
+ with urllib.request.urlopen(url, timeout=2) as response:
132
+ data = json.loads(response.read().decode())
133
+ return data['info']['version']
134
+ except Exception:
135
+ # Silently fail - don't interrupt user's work
136
+ return None
137
+
138
+
139
+ def parse_version(version_str: str) -> Tuple[int, ...]:
140
+ """Parse version string into tuple of integers for comparison.
141
+
142
+ Args:
143
+ version_str: Version string like "1.4.8"
144
+
145
+ Returns:
146
+ Tuple of integers like (1, 4, 8)
147
+ """
148
+ try:
149
+ return tuple(int(x) for x in version_str.split('.'))
150
+ except Exception:
151
+ return (0,)
152
+
153
+
154
+ def check_for_updates(current_version: str, force: bool = False) -> None:
155
+ """Check if a newer version is available and notify user.
156
+
157
+ Args:
158
+ current_version: Current installed version
159
+ force: If True, ignore cache and always check
160
+ """
161
+ # Allow disabling version check via environment variable
162
+ if os.environ.get('BATPLOT_NO_VERSION_CHECK', '').lower() in ('1', 'true', 'yes'):
163
+ return
164
+
165
+ cache_file = get_cache_file()
166
+ now = time.time()
167
+
168
+ # Check cache unless forced
169
+ if not force and cache_file.exists():
170
+ try:
171
+ with open(cache_file, 'r') as f:
172
+ cache = json.load(f)
173
+ # Check once per hour (3600 seconds)
174
+ if now - cache.get('timestamp', 0) < 3600:
175
+ # Use cached result
176
+ latest = cache.get('latest_version')
177
+ if latest and parse_version(latest) > parse_version(current_version):
178
+ _print_update_message(current_version, latest)
179
+ return
180
+ except Exception:
181
+ # Cache read failed, continue to check
182
+ pass
183
+
184
+ # Fetch latest version from PyPI
185
+ latest = get_latest_version()
186
+
187
+ # Update cache
188
+ try:
189
+ with open(cache_file, 'w') as f:
190
+ json.dump({
191
+ 'timestamp': now,
192
+ 'latest_version': latest,
193
+ 'current_version': current_version
194
+ }, f)
195
+ except Exception:
196
+ # Cache write failed, not critical
197
+ pass
198
+
199
+ # Notify user if newer version available
200
+ if latest and parse_version(latest) > parse_version(current_version):
201
+ _print_update_message(current_version, latest)
202
+
203
+
204
+ def _print_update_message(current: str, latest: str) -> None:
205
+ """Print update notification message.
206
+
207
+ Args:
208
+ current: Current version
209
+ latest: Latest available version
210
+ """
211
+ # Calculate box width (minimum 68, expand if needed for longer messages)
212
+ box_width = 68
213
+ custom_msg = UPDATE_INFO.get('custom_message')
214
+ update_notes = UPDATE_INFO.get('update_notes')
215
+ show_notes = UPDATE_INFO.get('show_update_notes', True)
216
+
217
+ # Calculate required width based on content
218
+ max_line_len = 68 # Default minimum width
219
+ if custom_msg:
220
+ max_line_len = max(max_line_len, len(custom_msg) + 4)
221
+ if update_notes and show_notes:
222
+ for note in update_notes:
223
+ max_line_len = max(max_line_len, len(note) + 4)
224
+ # Ensure box width is at least the calculated width
225
+ box_width = max(68, min(max_line_len, 100)) # Cap at 100 for readability
226
+
227
+ print(f"\n\033[93m╭{'─' * box_width}╮\033[0m")
228
+ print(f"\033[93m│\033[0m \033[1mA new version of batplot is available!\033[0m" + " " * max(0, box_width - 34) + "\033[93m│\033[0m")
229
+ print(f"\033[93m│\033[0m Current: \033[91m{current}\033[0m → Latest: \033[92m{latest}\033[0m" + " " * max(0, box_width - 20 - len(current) - len(latest)) + "\033[93m│\033[0m")
230
+
231
+ # Add custom message if provided
232
+ if custom_msg and custom_msg.strip():
233
+ # Truncate if too long to fit in box
234
+ msg = custom_msg[:box_width - 6] if len(custom_msg) > box_width - 6 else custom_msg
235
+ print(f"\033[93m│\033[0m {msg}" + " " * max(0, box_width - len(msg) - 4) + "\033[93m│\033[0m")
236
+
237
+ # Add update notes if provided
238
+ if update_notes and show_notes and isinstance(update_notes, list):
239
+ for note in update_notes:
240
+ if note and note.strip():
241
+ # Truncate if too long to fit in box
242
+ note_text = note[:box_width - 6] if len(note) > box_width - 6 else note
243
+ print(f"\033[93m│\033[0m {note_text}" + " " * max(0, box_width - len(note_text) - 4) + "\033[93m│\033[0m")
244
+
245
+ print(f"\033[93m│\033[0m Update with: \033[96mpip install --upgrade batplot\033[0m" + " " * max(0, box_width - 34) + "\033[93m│\033[0m")
246
+ print(f"\033[93m│\033[0m To disable this check: \033[96mexport BATPLOT_NO_VERSION_CHECK=1\033[0m" + " " * max(0, box_width - 45) + "\033[93m│\033[0m")
247
+ print(f"\033[93m╰{'─' * box_width}╯\033[0m\n")
248
+
249
+
250
+ if __name__ == '__main__':
251
+ # Test the version checker
252
+ from batplot import __version__
253
+ check_for_updates(__version__, force=True)
@@ -1,52 +0,0 @@
1
- batplot/__init__.py,sha256=AjJgj7OxrIM-uNCR6JvGnRjpVNZgCUbmj0VE_BpFFF8,118
2
- batplot/args.py,sha256=GXOO5jfTSmd5y_MiGyabh-mgJsCrg3mKVfTwe1eKOYc,34961
3
- batplot/batch.py,sha256=YQ7obCIqLCObwDbM7TXpOBh7g7BO95wZNsa2Fy84c6o,53858
4
- batplot/batplot.py,sha256=40lU1nY1NqeAOpzNG_vLF_L34COKhiA19pMpbvA3SJc,171885
5
- batplot/cif.py,sha256=JfHwNf3SHrcpALc_F5NjJmQ3lg71MBRSaIUJjGYPTx8,30120
6
- batplot/cli.py,sha256=ScDb2je8VQ0mz_z0SLCHEigiTuFPY5pb1snnzCouKms,5828
7
- batplot/color_utils.py,sha256=7InQLVo1XTg7sgAbltM2KeDSFJgr787YEaV9vJbIoWY,20460
8
- batplot/config.py,sha256=6nGY7fKN4T5KZUGQS2ArUBgEkLAL0j37XwG5SCVQgKA,6420
9
- batplot/converters.py,sha256=rR2WMPM0nR5E3eZI3gWbaJf_AfbdQx3urVSbJmZXNzo,8237
10
- batplot/cpc_interactive.py,sha256=HrrjaB8-CNYUitgl5zWMNvWQLZfxyFAtpSm67qoi-nE,238235
11
- batplot/electrochem_interactive.py,sha256=ti7V8BoAxUk4BD_vDRKAu5ydlHMl75htLvdVYFUUVsw,221778
12
- batplot/interactive.py,sha256=uerVR-56g2Ur8qDZ-cXffPbpYMQXEXiMNXCxyWZZ8k0,206259
13
- batplot/manual.py,sha256=pbRI6G4Pm12pOW8LrOLWWu7IEOtqWN3tRHtgge50LlA,11556
14
- batplot/modes.py,sha256=Utfal5IaV8rfoNyNFziUZpqRlpZAWJdiTc45DY-FJE8,37300
15
- batplot/operando.py,sha256=p2Ug1mFUQxaU702cTBGgJKb3_v1C2p3LLUwfXaVBpPY,28311
16
- batplot/operando_ec_interactive.py,sha256=TMB6rDpeolX0CgE2V7tWC24ffJrnbJomQSnTsTd8CNQ,305121
17
- batplot/plotting.py,sha256=hG2_EdDhF1Qpn1XfZKdCQ5-w_m9gUYFbr804UQ5QjsU,10841
18
- batplot/readers.py,sha256=kAI0AvYrdfGRZkvADJ4riN96IWtrH24aAoZpBtONTbw,112960
19
- batplot/session.py,sha256=05JsVi0ygMzOxVRRZ4klhE5Eh6eE6QxKR8p7_j6slBI,134429
20
- batplot/style.py,sha256=ig1ozX4dhEsXf5JKaPZOvgVS3CWx-BTFSc3vfAH3Y-E,62274
21
- batplot/ui.py,sha256=ifpbK74juUzLMCt-sJGVaWtpDb1NMRJzs2YyiwwafzY,35302
22
- batplot/utils.py,sha256=LY2-Axr3DsQMTxuXe48vSjrLJKEnkzkZjdSFdQizbpg,37599
23
- batplot/version_check.py,sha256=ztTHwqgWd8OlS9PLLY5A_TabWxBASDA_-5yyN15PZC8,9996
24
- batplot/data/USER_MANUAL.md,sha256=VYPvNZt3Fy8Z4Izr2FnQBw9vEaFTPkybhHDnF-OuKws,17694
25
- batplot-1.8.1.dist-info/licenses/LICENSE,sha256=2PAnHeCiTfgI7aKZLWr0G56HI9fGKQ0CEbQ02H-yExQ,1065
26
- batplot_backup_20251121_223043/__init__.py,sha256=3s2DUQuTbWs65hoN9cQQ8IiJbaFJY8fNxiCpwRBYoOA,118
27
- batplot_backup_20251121_223043/args.py,sha256=OH-h84QhN-IhMS8sPAsSEqccHD3wpeMgmXa_fqv5xtg,21215
28
- batplot_backup_20251121_223043/batch.py,sha256=oI7PONJyciHDOqNPq-8fnOQMyn9CpAdVznKaEdsy0ig,48650
29
- batplot_backup_20251121_223043/batplot.py,sha256=cJOqfqEWd3vW4prlt0i2Ih6BqopnjFiRP_fAxCMHcds,157883
30
- batplot_backup_20251121_223043/cif.py,sha256=MeMHq7GvFwrFwpASD4XkqbHVBiBrJxmG112IPThfbZo,17564
31
- batplot_backup_20251121_223043/cli.py,sha256=lq-0MSCHouGm1qXMYFlI2YMwAMZZSPQxhfMrR8-vdTM,2622
32
- batplot_backup_20251121_223043/color_utils.py,sha256=jQzsR1Q2cfn7luIdK5aMW4BZhIKb5Q_Q9NfmiUk0AwA,8467
33
- batplot_backup_20251121_223043/config.py,sha256=MKtmMiQrY9WmghEpcdyBwpiT-Xl3SwLVZTt0DhuB7Yc,1939
34
- batplot_backup_20251121_223043/converters.py,sha256=O7zvCNTztrXXSxJtm2GZkseYt4agidA6URSCugh953I,3090
35
- batplot_backup_20251121_223043/cpc_interactive.py,sha256=Z8Sil20F8ibhZUFm1s2oKWGr_tDFwbPBCvEzfb3xADQ,157886
36
- batplot_backup_20251121_223043/electrochem_interactive.py,sha256=FxFuq7945tIZJWWxdXkh8ZGzyCV5u8khVIr9bFCtKTw,173915
37
- batplot_backup_20251121_223043/interactive.py,sha256=dAntE1WkAC2pf50wK-jOLmO-t3BOt9NgtgrFmyM_0ac,181928
38
- batplot_backup_20251121_223043/modes.py,sha256=s4eUHfbl-uORt9kR7Rl56xvirMkPXSsU_dVVv8PrOSE,24698
39
- batplot_backup_20251121_223043/operando.py,sha256=SABx1BQguoXXsG5PFAbp_CMvAz9vDA3JKRa4lcKGCm0,22980
40
- batplot_backup_20251121_223043/operando_ec_interactive.py,sha256=k9_r70OKqclJQUOT3c_W2DxXfkF9qVRCcUxo-QuTwsI,261415
41
- batplot_backup_20251121_223043/plotting.py,sha256=fwzcdKQcHZDamtJj33zfs--Kwc81KoMhn91EQ8Vkeq8,4157
42
- batplot_backup_20251121_223043/readers.py,sha256=O1CbGE5sedFn1TvCAvIB39Y6zCqcBt3ehvIkf0b6rYw,78339
43
- batplot_backup_20251121_223043/session.py,sha256=CzzDZw_7rb8r2seVZZbP6dLoDl8nhhViKgB-qaT5-5s,111705
44
- batplot_backup_20251121_223043/style.py,sha256=xg-tj6bEbFUVjjxYMokiLehS4tSfKanLIQKtly3cAP0,51318
45
- batplot_backup_20251121_223043/ui.py,sha256=K0XZWyiuBRNkFod9mgZyJ9CLN78GR1-hh6EznnIb5S8,31208
46
- batplot_backup_20251121_223043/utils.py,sha256=jydA0JxsCWWAudXEwSjlxTG17y2F8U6hIAukAzi1P0g,32526
47
- batplot_backup_20251121_223043/version_check.py,sha256=vlHkGkgUJcD_Z4KZmwonxZvKZh0MwHLaBSxaLPc66AQ,4555
48
- batplot-1.8.1.dist-info/METADATA,sha256=3n6IsXn-SgLaDVHF6t4HCMmzDpf0Tkkbp23Dva98oN8,7406
49
- batplot-1.8.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
50
- batplot-1.8.1.dist-info/entry_points.txt,sha256=73GgH3Zs-qGIvgiyQLgGsSW-ryOwPPKHveOW6TDIR5Q,82
51
- batplot-1.8.1.dist-info/top_level.txt,sha256=CgqK4RpsYnUFAcqO4bLOnEhCoPY4IPEGLPkiDlzLIxg,39
52
- batplot-1.8.1.dist-info/RECORD,,