supervertaler 1.9.146__py3-none-any.whl → 1.9.147__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.
Supervertaler.py CHANGED
@@ -34,7 +34,7 @@ License: MIT
34
34
  """
35
35
 
36
36
  # Version Information.
37
- __version__ = "1.9.146"
37
+ __version__ = "1.9.147"
38
38
  __phase__ = "0.9"
39
39
  __release_date__ = "2026-01-20"
40
40
  __edition__ = "Qt"
@@ -65,18 +65,158 @@ def get_user_data_path() -> Path:
65
65
  """
66
66
  Get the path to user data directory.
67
67
 
68
- In frozen builds (EXE): 'user_data' folder next to the EXE
69
- In development: 'user_data' folder next to the script
68
+ This function returns a PERSISTENT location for user data that survives
69
+ pip upgrades and reinstalls. The location varies by context:
70
70
 
71
- The build process copies user_data directly next to the EXE for easy access.
71
+ 1. FROZEN BUILDS (Windows EXE): 'user_data' folder next to the EXE
72
+ - This allows the EXE to be portable (copy folder = copy everything)
73
+ - Path: C:/SomeFolder/Supervertaler/user_data/
74
+
75
+ 2. PIP INSTALLS: Platform-specific user data directory
76
+ - Windows: %LOCALAPPDATA%/Supervertaler/ (e.g., C:/Users/John/AppData/Local/Supervertaler/)
77
+ - macOS: ~/Library/Application Support/Supervertaler/
78
+ - Linux: ~/.local/share/Supervertaler/ (XDG_DATA_HOME)
79
+ - This location persists across pip upgrades!
80
+
81
+ 3. DEVELOPMENT MODE: 'user_data' or 'user_data_private' next to script
82
+ - Developers can use ENABLE_PRIVATE_FEATURES to use user_data_private/
83
+
84
+ The key insight: pip installs wipe site-packages on upgrade, so we MUST
85
+ store user data outside the package directory for pip users.
72
86
  """
73
87
  if getattr(sys, 'frozen', False):
74
- # Frozen build: user_data is next to the EXE (copied by build script)
88
+ # =====================================================================
89
+ # FROZEN BUILD (EXE): Keep data next to executable for portability
90
+ # =====================================================================
91
+ # Users can copy the entire folder to a USB drive and it works.
92
+ # The build script copies user_data/ next to Supervertaler.exe
75
93
  return Path(sys.executable).parent / "user_data"
94
+
95
+ # Check if we're running from site-packages (pip install)
96
+ script_path = Path(__file__).resolve()
97
+ is_pip_install = "site-packages" in str(script_path)
98
+
99
+ if is_pip_install:
100
+ # =================================================================
101
+ # PIP INSTALL: Use platform-specific persistent location
102
+ # =================================================================
103
+ # This survives pip upgrades because it's OUTSIDE site-packages!
104
+ try:
105
+ from platformdirs import user_data_dir
106
+ return Path(user_data_dir("Supervertaler", "MichaelBeijer"))
107
+ except ImportError:
108
+ # Fallback if platformdirs not available (shouldn't happen)
109
+ if sys.platform == 'win32':
110
+ base = Path(os.environ.get('LOCALAPPDATA', os.path.expanduser('~')))
111
+ return base / "Supervertaler"
112
+ elif sys.platform == 'darwin':
113
+ return Path.home() / "Library" / "Application Support" / "Supervertaler"
114
+ else:
115
+ # Linux/BSD - follow XDG spec
116
+ xdg_data = os.environ.get('XDG_DATA_HOME', os.path.expanduser('~/.local/share'))
117
+ return Path(xdg_data) / "Supervertaler"
76
118
  else:
77
- # Development: user_data next to script
119
+ # =================================================================
120
+ # DEVELOPMENT MODE: Use folder next to script
121
+ # =================================================================
78
122
  return Path(__file__).parent / "user_data"
79
123
 
124
+
125
+ def migrate_user_data_if_needed(new_path: Path) -> bool:
126
+ """
127
+ Migrate user data from old location (inside site-packages) to new location.
128
+
129
+ This handles the transition for existing pip users whose data was stored
130
+ inside the package directory (which gets wiped on upgrade).
131
+
132
+ Returns True if migration was performed, False otherwise.
133
+ """
134
+ import shutil
135
+
136
+ # Only migrate for pip installs (frozen builds keep data next to EXE)
137
+ if getattr(sys, 'frozen', False):
138
+ return False
139
+
140
+ # Check if we're in a pip install
141
+ script_path = Path(__file__).resolve()
142
+ if "site-packages" not in str(script_path):
143
+ return False # Development mode, no migration needed
144
+
145
+ # Old location: user_data folder inside the package in site-packages
146
+ old_path = script_path.parent / "user_data"
147
+
148
+ # If old location doesn't exist or is empty, no migration needed
149
+ if not old_path.exists():
150
+ return False
151
+
152
+ # Check if old location has actual content (not just empty dirs)
153
+ old_has_content = False
154
+ for item in old_path.rglob('*'):
155
+ if item.is_file():
156
+ old_has_content = True
157
+ break
158
+
159
+ if not old_has_content:
160
+ return False
161
+
162
+ # If new location already has content, don't overwrite (user may have set up fresh)
163
+ new_has_content = False
164
+ if new_path.exists():
165
+ for item in new_path.rglob('*'):
166
+ if item.is_file():
167
+ new_has_content = True
168
+ break
169
+
170
+ if new_has_content:
171
+ # Both have content - log but don't migrate (user may have set up manually)
172
+ print(f"[Migration] Both old and new data locations have content:")
173
+ print(f" Old: {old_path}")
174
+ print(f" New: {new_path}")
175
+ print(f"[Migration] Keeping new location. Old data preserved in site-packages.")
176
+ return False
177
+
178
+ # Perform migration
179
+ print(f"[Migration] Migrating user data from old location...")
180
+ print(f" From: {old_path}")
181
+ print(f" To: {new_path}")
182
+
183
+ try:
184
+ # Ensure new path parent exists
185
+ new_path.parent.mkdir(parents=True, exist_ok=True)
186
+
187
+ # Copy entire directory tree (use copy, not move, for safety)
188
+ if new_path.exists():
189
+ # Merge into existing empty directory
190
+ for item in old_path.iterdir():
191
+ dest = new_path / item.name
192
+ if item.is_dir():
193
+ shutil.copytree(item, dest, dirs_exist_ok=True)
194
+ else:
195
+ shutil.copy2(item, dest)
196
+ else:
197
+ shutil.copytree(old_path, new_path)
198
+
199
+ print(f"[Migration] ✅ Successfully migrated user data!")
200
+ print(f"[Migration] Your API keys, TMs, glossaries, and prompts are now in:")
201
+ print(f" {new_path}")
202
+
203
+ # Leave a marker file in the old location so users know what happened
204
+ marker = old_path / "_MIGRATED_TO_NEW_LOCATION.txt"
205
+ marker.write_text(
206
+ f"Your Supervertaler data has been migrated to a persistent location:\n"
207
+ f"{new_path}\n\n"
208
+ f"This location survives pip upgrades.\n"
209
+ f"You can safely delete this old folder.\n"
210
+ f"Migration date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
211
+ )
212
+
213
+ return True
214
+
215
+ except Exception as e:
216
+ print(f"[Migration] ⚠️ Error during migration: {e}")
217
+ print(f"[Migration] Your data is still in: {old_path}")
218
+ return False
219
+
80
220
  import threading
81
221
  import time # For delays in Superlookup
82
222
  import re
@@ -5167,17 +5307,25 @@ class SupervertalerQt(QMainWindow):
5167
5307
  # ============================================================================
5168
5308
  # USER DATA PATH INITIALIZATION
5169
5309
  # ============================================================================
5170
- # Set up user data paths - handles both development and frozen (EXE) builds
5171
- # In frozen builds, user_data is copied directly next to the EXE by the build script.
5310
+ # User data is stored in a PERSISTENT location that survives pip upgrades:
5311
+ # - Windows: %LOCALAPPDATA%\Supervertaler\
5312
+ # - macOS: ~/Library/Application Support/Supervertaler/
5313
+ # - Linux: ~/.local/share/Supervertaler/
5314
+ # - EXE: user_data/ folder next to executable (portable mode)
5315
+ # - Dev: user_data_private/ or user_data/ next to script
5172
5316
  from modules.database_manager import DatabaseManager
5173
5317
 
5174
5318
  if ENABLE_PRIVATE_FEATURES:
5175
5319
  # Developer mode: use private folder (git-ignored)
5176
5320
  self.user_data_path = Path(__file__).parent / "user_data_private"
5177
5321
  else:
5178
- # Normal mode: use the helper function
5322
+ # Normal mode: use the helper function (handles pip vs EXE vs dev)
5179
5323
  self.user_data_path = get_user_data_path()
5180
5324
 
5325
+ # Migrate old data from site-packages to new persistent location (pip users)
5326
+ # This is a one-time migration for users upgrading from older versions
5327
+ migrate_user_data_if_needed(self.user_data_path)
5328
+
5181
5329
  # Ensure user_data directory exists (creates empty folder if missing)
5182
5330
  self.user_data_path.mkdir(parents=True, exist_ok=True)
5183
5331
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: supervertaler
3
- Version: 1.9.146
3
+ Version: 1.9.147
4
4
  Summary: Professional AI-powered translation workbench with multi-LLM support, glossary system, TM, spellcheck, voice commands, and PyQt6 interface. Batteries included (core).
5
5
  Home-page: https://supervertaler.com
6
6
  Author: Michael Beijer
@@ -46,6 +46,7 @@ Requires-Dist: chardet>=5.0.0
46
46
  Requires-Dist: pyyaml>=6.0.0
47
47
  Requires-Dist: markdown>=3.4.0
48
48
  Requires-Dist: pyspellchecker>=0.7.0
49
+ Requires-Dist: platformdirs>=4.0.0
49
50
  Requires-Dist: sounddevice>=0.4.6
50
51
  Requires-Dist: numpy>=1.24.0
51
52
  Requires-Dist: PyMuPDF>=1.23.0
@@ -71,7 +72,7 @@ Dynamic: home-page
71
72
  Dynamic: license-file
72
73
  Dynamic: requires-python
73
74
 
74
- # 🚀 Supervertaler v1.9.146
75
+ # 🚀 Supervertaler v1.9.147
75
76
 
76
77
  [![PyPI version](https://badge.fury.io/py/supervertaler.svg)](https://pypi.org/project/Supervertaler/)
77
78
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
@@ -79,7 +80,20 @@ Dynamic: requires-python
79
80
 
80
81
  AI-enhanced CAT tool with multi-LLM support (GPT-4, Claude, Gemini, Ollama), innovative Superlookup concordance system offering access to multiple terminology sources (TMs, glossaries, web resources, etc.), and seamless CAT tool integration (memoQ, Trados, CafeTran, Phrase).
81
82
 
82
- **Current Version:** v1.9.146 (January 21, 2026)
83
+ **Current Version:** v1.9.147 (January 21, 2026)
84
+
85
+ ### NEW in v1.9.147 - 📁 Persistent User Data Location
86
+
87
+ **No More Data Loss on Upgrade!** User data (API keys, TMs, glossaries, prompts, settings) is now stored in a persistent location that survives `pip install --upgrade`:
88
+
89
+ | Platform | User Data Location |
90
+ |----------|-------------------|
91
+ | **Windows** | `%LOCALAPPDATA%\MichaelBeijer\Supervertaler\` |
92
+ | **macOS** | `~/Library/Application Support/Supervertaler/` |
93
+ | **Linux** | `~/.local/share/Supervertaler/` |
94
+ | **Windows EXE** | `user_data\` next to executable (portable) |
95
+
96
+ Existing data is automatically migrated on first run after upgrade.
83
97
 
84
98
  ### FIXED in v1.9.146 - 🔑 Gemini/Google API Key Alias
85
99
 
@@ -1,4 +1,4 @@
1
- Supervertaler.py,sha256=vNxA4ZPfXTerYIDaHRsbz842S9TbC634rraFSPV6VZI,2153239
1
+ Supervertaler.py,sha256=0Vkn41czCn0bkCEQ-Vpd1Ee3ifsLUjeJT5QY3wYPNkg,2159745
2
2
  modules/__init__.py,sha256=G58XleS-EJ2sX4Kehm-3N2m618_W2Es0Kg8CW_eBG7g,327
3
3
  modules/ai_actions.py,sha256=i5MJcM-7Y6CAvKUwxmxrVHeoZAVtAP7aRDdWM5KLkO0,33877
4
4
  modules/ai_attachment_manager.py,sha256=mA5ISI22qN9mH3DQFF4gOTciDyBt5xVR7sHTkgkTIlw,11361
@@ -77,9 +77,9 @@ modules/unified_prompt_manager_qt.py,sha256=kpR-Tk1xmVyJGHnZdHm6NbGQPTZ1jB8t4tI_
77
77
  modules/voice_commands.py,sha256=iBb-gjWxRMLhFH7-InSRjYJz1EIDBNA2Pog8V7TtJaY,38516
78
78
  modules/voice_dictation.py,sha256=QmitXfkG-vRt5hIQATjphHdhXfqmwhzcQcbXB6aRzIg,16386
79
79
  modules/voice_dictation_lite.py,sha256=jorY0BmWE-8VczbtGrWwt1zbnOctMoSlWOsQrcufBcc,9423
80
- supervertaler-1.9.146.dist-info/licenses/LICENSE,sha256=m28u-4qL5nXIWnJ6xlQVw__H30rWFtRK3pCOais2OuY,1092
81
- supervertaler-1.9.146.dist-info/METADATA,sha256=cPeDrCE6z6Kbfb2_vdQFxORfwE-WJQim-v6YFBxmgPs,43796
82
- supervertaler-1.9.146.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
83
- supervertaler-1.9.146.dist-info/entry_points.txt,sha256=NP4hiCvx-_30YYKqgr-jfJYQvHr1qTYBMfoVmKIXSM8,53
84
- supervertaler-1.9.146.dist-info/top_level.txt,sha256=9tUHBYUSfaE4S2E4W3eavJsDyYymkwLfeWAHHAPT6Dk,22
85
- supervertaler-1.9.146.dist-info/RECORD,,
80
+ supervertaler-1.9.147.dist-info/licenses/LICENSE,sha256=m28u-4qL5nXIWnJ6xlQVw__H30rWFtRK3pCOais2OuY,1092
81
+ supervertaler-1.9.147.dist-info/METADATA,sha256=cqvLJ6GY6wgzZOqBQynIOMb7CiCaS46UQJbaI0qorSY,44450
82
+ supervertaler-1.9.147.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
83
+ supervertaler-1.9.147.dist-info/entry_points.txt,sha256=NP4hiCvx-_30YYKqgr-jfJYQvHr1qTYBMfoVmKIXSM8,53
84
+ supervertaler-1.9.147.dist-info/top_level.txt,sha256=9tUHBYUSfaE4S2E4W3eavJsDyYymkwLfeWAHHAPT6Dk,22
85
+ supervertaler-1.9.147.dist-info/RECORD,,