TonieToolbox 0.1.4__py3-none-any.whl → 0.1.6__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.
TonieToolbox/__init__.py CHANGED
@@ -2,4 +2,4 @@
2
2
  TonieToolbox - Convert audio files to Tonie box compatible format
3
3
  """
4
4
 
5
- __version__ = '0.1.4'
5
+ __version__ = '0.1.6'
TonieToolbox/__main__.py CHANGED
@@ -15,6 +15,7 @@ from .tonie_analysis import check_tonie_file, split_to_opus_files
15
15
  from .dependency_manager import get_ffmpeg_binary, get_opus_binary
16
16
  from .logger import setup_logging, get_logger
17
17
  from .filename_generator import guess_output_filename
18
+ from .version_handler import check_for_updates, clear_version_cache
18
19
 
19
20
  def main():
20
21
  """Entry point for the TonieToolbox application."""
@@ -45,6 +46,15 @@ def main():
45
46
  parser.add_argument('--detailed-compare', action='store_true',
46
47
  help='Show detailed OGG page differences when comparing files')
47
48
 
49
+ # Version check options
50
+ version_group = parser.add_argument_group('Version Check Options')
51
+ version_group.add_argument('--skip-update-check', action='store_true',
52
+ help='Skip checking for updates')
53
+ version_group.add_argument('--force-refresh-cache', action='store_true',
54
+ help='Force refresh of update information from PyPI')
55
+ version_group.add_argument('--clear-version-cache', action='store_true',
56
+ help='Clear cached version information')
57
+
48
58
  log_group = parser.add_argument_group('Logging Options')
49
59
  log_level_group = log_group.add_mutually_exclusive_group()
50
60
  log_level_group.add_argument('--debug', action='store_true', help='Enable debug logging')
@@ -67,7 +77,22 @@ def main():
67
77
 
68
78
  setup_logging(log_level)
69
79
  logger = get_logger('main')
70
- logger.debug("Starting TonieToolbox with log level: %s", logging.getLevelName(log_level))
80
+ logger.debug("Starting TonieToolbox v%s with log level: %s", __version__, logging.getLevelName(log_level))
81
+
82
+ # Handle version cache operations
83
+ if args.clear_version_cache:
84
+ if clear_version_cache():
85
+ logger.info("Version cache cleared successfully")
86
+ else:
87
+ logger.info("No version cache to clear or error clearing cache")
88
+
89
+ # Check for updates
90
+ if not args.skip_update_check:
91
+ logger.debug("Checking for updates (force_refresh=%s)", args.force_refresh_cache)
92
+ check_for_updates(
93
+ quiet=args.silent or args.quiet,
94
+ force_refresh=args.force_refresh_cache
95
+ )
71
96
 
72
97
  ffmpeg_binary = args.ffmpeg
73
98
  if ffmpeg_binary is None:
@@ -0,0 +1,193 @@
1
+ """
2
+ Version handler to check if the latest version of TonieToolbox is being used.
3
+ """
4
+
5
+ import json
6
+ import logging
7
+ import os
8
+ import time
9
+ from urllib import request
10
+ from urllib.error import URLError
11
+
12
+ from . import __version__
13
+ from .logger import get_logger
14
+
15
+ # Cache filename for version information
16
+ CACHE_DIR = os.path.join(os.path.expanduser("~"), ".tonietoolbox")
17
+ CACHE_FILE = os.path.join(CACHE_DIR, "version_cache.json")
18
+ CACHE_EXPIRY = 86400 # 24 hours in seconds
19
+
20
+
21
+ def get_pypi_version(force_refresh=False):
22
+ """
23
+ Get the latest version of TonieToolbox from PyPI.
24
+
25
+ Args:
26
+ force_refresh: If True, ignore the cache and fetch directly from PyPI
27
+
28
+ Returns:
29
+ tuple: (latest_version, None) on success, (current_version, error_message) on failure
30
+ """
31
+ logger = get_logger("version_handler")
32
+ logger.debug("Checking for latest version (force_refresh=%s)", force_refresh)
33
+ logger.debug("Current version: %s", __version__)
34
+
35
+ try:
36
+ # Check if we have a recent cache and should use it
37
+ if not force_refresh and os.path.exists(CACHE_FILE):
38
+ try:
39
+ with open(CACHE_FILE, "r") as f:
40
+ cache_data = json.load(f)
41
+
42
+ cached_version = cache_data.get("version")
43
+ cache_timestamp = cache_data.get("timestamp", 0)
44
+ cache_age = time.time() - cache_timestamp
45
+
46
+ logger.debug("Cache info: version=%s, age=%d seconds (expires after %d)",
47
+ cached_version, cache_age, CACHE_EXPIRY)
48
+
49
+ if cache_age < CACHE_EXPIRY:
50
+ logger.debug("Using cached version info: %s", cached_version)
51
+ return cached_version, None
52
+ else:
53
+ logger.debug("Cache expired (%d seconds old), refreshing from PyPI", cache_age)
54
+ except (json.JSONDecodeError, KeyError) as e:
55
+ logger.debug("Cache file corrupt, will fetch from PyPI: %s", e)
56
+ else:
57
+ if force_refresh:
58
+ logger.debug("Forced refresh requested, bypassing cache")
59
+ else:
60
+ logger.debug("No cache found, fetching from PyPI")
61
+
62
+ # Fetch from PyPI
63
+ logger.debug("Fetching latest version from PyPI")
64
+ with request.urlopen("https://pypi.org/pypi/TonieToolbox/json", timeout=2) as response:
65
+ pypi_data = json.loads(response.read().decode("utf-8"))
66
+ latest_version = pypi_data["info"]["version"]
67
+
68
+ # Update cache
69
+ if not os.path.exists(CACHE_DIR):
70
+ os.makedirs(CACHE_DIR, exist_ok=True)
71
+
72
+ with open(CACHE_FILE, "w") as f:
73
+ cache_data = {
74
+ "version": latest_version,
75
+ "timestamp": time.time()
76
+ }
77
+ json.dump(cache_data, f)
78
+ logger.debug("Updated cache: %s", cache_data)
79
+
80
+ logger.debug("Latest version from PyPI: %s", latest_version)
81
+ return latest_version, None
82
+
83
+ except (URLError, json.JSONDecodeError) as e:
84
+ logger.debug("Failed to fetch version from PyPI: %s", e)
85
+ return __version__, f"Failed to check for updates: {str(e)}"
86
+ except Exception as e:
87
+ logger.debug("Unexpected error checking for updates: %s", e)
88
+ return __version__, f"Unexpected error checking for updates: {str(e)}"
89
+
90
+
91
+ def compare_versions(v1, v2):
92
+ """
93
+ Compare two version strings.
94
+
95
+ Args:
96
+ v1: First version string
97
+ v2: Second version string
98
+
99
+ Returns:
100
+ int: -1 if v1 < v2, 0 if v1 == v2, 1 if v1 > v2
101
+ """
102
+ logger = get_logger("version_handler")
103
+ logger.debug("Comparing versions: '%s' vs '%s'", v1, v2)
104
+
105
+ try:
106
+ v1_parts = [int(x) for x in v1.split('.')]
107
+ v2_parts = [int(x) for x in v2.split('.')]
108
+
109
+ logger.debug("Version parts: %s vs %s", v1_parts, v2_parts)
110
+
111
+ for i in range(max(len(v1_parts), len(v2_parts))):
112
+ v1_part = v1_parts[i] if i < len(v1_parts) else 0
113
+ v2_part = v2_parts[i] if i < len(v2_parts) else 0
114
+
115
+ logger.debug("Comparing part %d: %d vs %d", i, v1_part, v2_part)
116
+
117
+ if v1_part < v2_part:
118
+ logger.debug("Result: '%s' is OLDER than '%s'", v1, v2)
119
+ return -1
120
+ elif v1_part > v2_part:
121
+ logger.debug("Result: '%s' is NEWER than '%s'", v1, v2)
122
+ return 1
123
+
124
+ logger.debug("Result: versions are EQUAL")
125
+ return 0
126
+ except Exception as e:
127
+ logger.debug("Error comparing versions '%s' and '%s': %s", v1, v2, e)
128
+ # On error, assume versions are equal
129
+ return 0
130
+
131
+
132
+ def check_for_updates(quiet=False, force_refresh=False):
133
+ """
134
+ Check if the current version of TonieToolbox is the latest.
135
+
136
+ Args:
137
+ quiet: If True, will not log any information messages
138
+ force_refresh: If True, bypass cache and check PyPI directly
139
+
140
+ Returns:
141
+ tuple: (is_latest, latest_version, message)
142
+ is_latest: boolean indicating if the current version is the latest
143
+ latest_version: string with the latest version
144
+ message: string message about the update status or error
145
+ """
146
+ logger = get_logger("version_handler")
147
+ current_version = __version__
148
+
149
+ logger.debug("Starting update check (quiet=%s, force_refresh=%s)", quiet, force_refresh)
150
+ latest_version, error = get_pypi_version(force_refresh)
151
+
152
+ if error:
153
+ logger.debug("Error occurred during update check: %s", error)
154
+ return True, current_version, error
155
+
156
+ compare_result = compare_versions(current_version, latest_version)
157
+ is_latest = compare_result >= 0 # current >= latest
158
+
159
+ logger.debug("Version comparison result: %d (is_latest=%s)", compare_result, is_latest)
160
+
161
+ if is_latest:
162
+ message = f"You are using the latest version of TonieToolbox ({current_version})"
163
+ if not quiet:
164
+ logger.debug(message)
165
+ else:
166
+ message = f"Update available! Current version: {current_version}, Latest version: {latest_version}"
167
+ if not quiet:
168
+ logger.info(message)
169
+ logger.info("Consider upgrading with: pip install --upgrade TonieToolbox")
170
+
171
+ return is_latest, latest_version, message
172
+
173
+
174
+ def clear_version_cache():
175
+ """
176
+ Clear the version cache file to force a refresh on next check.
177
+
178
+ Returns:
179
+ bool: True if cache was cleared, False otherwise
180
+ """
181
+ logger = get_logger("version_handler")
182
+
183
+ try:
184
+ if os.path.exists(CACHE_FILE):
185
+ logger.debug("Removing version cache file: %s", CACHE_FILE)
186
+ os.remove(CACHE_FILE)
187
+ return True
188
+ else:
189
+ logger.debug("No cache file to remove")
190
+ return False
191
+ except Exception as e:
192
+ logger.debug("Error clearing cache: %s", e)
193
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: TonieToolbox
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: Convert audio files to Tonie box compatible format
5
5
  Home-page: https://github.com/Quentendo64/TonieToolbox
6
6
  Author: Quentendo64
@@ -1,5 +1,5 @@
1
- TonieToolbox/__init__.py,sha256=0RSXJddUBhbuu6nBzdO2-vzujCRbuT5wDnjUbwCFOOc,96
2
- TonieToolbox/__main__.py,sha256=qOWIB6JQyEBXyFBEIYbqNtXgFFRrUoHQVnBWiX-pEfw,7114
1
+ TonieToolbox/__init__.py,sha256=LTELDMNigo883omB6nSwss4YveBM23FSsESuIQyqSGg,96
2
+ TonieToolbox/__main__.py,sha256=zMaoT7-0JUT3PiU5A2xKNgig6NS1PUh4vDKUebJVdYg,8280
3
3
  TonieToolbox/audio_conversion.py,sha256=10PayO1VQDGee2bcO6JD8zRSFoJRJhO2pBeba5k15vk,7998
4
4
  TonieToolbox/constants.py,sha256=QQWQpnCI65GByLlXLOkt2n8nALLu4m6BWp0zuhI3M04,2021
5
5
  TonieToolbox/dependency_manager.py,sha256=sr7PMBsqQ26bYszM-7Ay-UbKPuBJGyeJV3y1BPAOiBQ,15028
@@ -11,9 +11,10 @@ TonieToolbox/tonie_analysis.py,sha256=4eOzxHL_g0TJFhuexNHcZXivxZ7eb5xfb9-efUZ02W
11
11
  TonieToolbox/tonie_file.py,sha256=nIS4qhpBKIyPvTU39yYljRidpY6cz78halXlz3HJy9w,15294
12
12
  TonieToolbox/tonie_header.proto,sha256=WaWfwO4VrwGtscK2ujfDRKtpeBpaVPoZhI8iMmR-C0U,202
13
13
  TonieToolbox/tonie_header_pb2.py,sha256=s5bp4ULTEekgq6T61z9fDkRavyPM-3eREs20f_Pxxe8,3665
14
- tonietoolbox-0.1.4.dist-info/licenses/LICENSE.md,sha256=rGoga9ZAgNco9fBapVFpWf6ri7HOBp1KRnt1uIruXMk,35190
15
- tonietoolbox-0.1.4.dist-info/METADATA,sha256=SJQYHwY4DhDOQcu3Dv4-hJgkF-CdmKw5soEsGv2a3i0,8971
16
- tonietoolbox-0.1.4.dist-info/WHEEL,sha256=lTU6B6eIfYoiQJTZNc-fyaR6BpL6ehTzU3xGYxn2n8k,91
17
- tonietoolbox-0.1.4.dist-info/entry_points.txt,sha256=oqpeyBxel7aScg35Xr4gZKnf486S5KW9okqeBwyJxxc,60
18
- tonietoolbox-0.1.4.dist-info/top_level.txt,sha256=Wkkm-2p7I3ENfS7ZbYtYUB2g-xwHrXVlERHfonsOPuE,13
19
- tonietoolbox-0.1.4.dist-info/RECORD,,
14
+ TonieToolbox/version_handler.py,sha256=KU7rS07RL6IZZL2rk4TJ9oKrAutiWvPBOr7qgZLIogI,7108
15
+ tonietoolbox-0.1.6.dist-info/licenses/LICENSE.md,sha256=rGoga9ZAgNco9fBapVFpWf6ri7HOBp1KRnt1uIruXMk,35190
16
+ tonietoolbox-0.1.6.dist-info/METADATA,sha256=xjwX7xRYP52Vs-flUlTtrxTUlaRMCLMrhtSbw9dOZDo,8971
17
+ tonietoolbox-0.1.6.dist-info/WHEEL,sha256=lTU6B6eIfYoiQJTZNc-fyaR6BpL6ehTzU3xGYxn2n8k,91
18
+ tonietoolbox-0.1.6.dist-info/entry_points.txt,sha256=oqpeyBxel7aScg35Xr4gZKnf486S5KW9okqeBwyJxxc,60
19
+ tonietoolbox-0.1.6.dist-info/top_level.txt,sha256=Wkkm-2p7I3ENfS7ZbYtYUB2g-xwHrXVlERHfonsOPuE,13
20
+ tonietoolbox-0.1.6.dist-info/RECORD,,