Skip to content

Commit 17a622a

Browse files
authored
DownloadJDK class refactor + types StrPath & PathAction
1 parent ce870c7 commit 17a622a

File tree

1 file changed

+44
-23
lines changed

1 file changed

+44
-23
lines changed

thonnycontrib/thonny-py5mode/install_jdk.py

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
from pathlib import Path, PurePath
1010
from threading import Thread
1111

12-
from os import environ as env, scandir, rename
12+
from os import environ as env, scandir, rename, PathLike
1313
from os.path import islink, realpath
1414

15-
from typing import Literal
15+
from typing import Callable, Literal, TypeAlias
1616
from collections.abc import Iterable, Iterator
1717

1818
import tkinter as tk
@@ -22,6 +22,12 @@
2222
from thonny import get_workbench, ui_utils, THONNY_USER_DIR
2323
from thonny.languages import tr
2424

25+
StrPath: TypeAlias = str | PathLike[str]
26+
'''A type representing string-based filesystem paths.'''
27+
28+
PathAction: TypeAlias = Callable[[StrPath], None]
29+
'''Represents an action applied to a single path-like object.'''
30+
2531
_JDK_PATTERN = re.compile(r"""
2632
(?:java|jdk) # Match 'java' or 'jdk' (non-capturing group)
2733
-? # Match optional hyphen '-'
@@ -82,7 +88,7 @@ def get_thonny_jdk_install() -> PurePath | Literal['']:
8288
return '' # No JDK with required version found in THONNY_USER_DIR
8389

8490

85-
def set_java_home(jdk_path: PurePath | str):
91+
def set_java_home(jdk_path: StrPath):
8692
'''Add JDK path to config file (tools > options > general > env vars).'''
8793
jdk_path = str(adjust_jdk_path(jdk_path))
8894
env['JAVA_HOME'] = jdk_path # Python's process points to Thonny's JDK
@@ -97,7 +103,7 @@ def set_java_home(jdk_path: PurePath | str):
97103
showinfo('JAVA_HOME', jdk_path, parent=workbench)
98104

99105

100-
def adjust_jdk_path(jdk_path: PurePath | str) -> PurePath:
106+
def adjust_jdk_path(jdk_path: StrPath) -> PurePath:
101107
'''Adjust JDK path for the specificity of current platform.'''
102108
jdk_path = PurePath(jdk_path)
103109

@@ -108,7 +114,7 @@ def adjust_jdk_path(jdk_path: PurePath | str) -> PurePath:
108114
return jdk_path
109115

110116

111-
def create_java_home_entry_from_path(jdk_path: PurePath | str) -> str:
117+
def create_java_home_entry_from_path(jdk_path: StrPath) -> str:
112118
'''Prefix JDK path with "JAVA_HOME=" to form a Thonny environment entry.'''
113119
return f'JAVA_HOME={jdk_path}'
114120

@@ -123,28 +129,23 @@ def _non_java_home_predicate(entry: str) -> bool:
123129
return not entry.startswith('JAVA_HOME=')
124130

125131

126-
def get_all_thonny_folders() -> list[str]:
127-
"""Return reverse-sorted names of subfolders within Thonny's user folder."""
128-
with scandir(THONNY_USER_DIR) as entries:
129-
return sorted((e.name for e in entries if e.is_dir()), reverse=True)
130-
131-
132-
def get_all_thonny_folder_paths() -> Iterator[Path]:
133-
'''Find all subfolder paths within Thonny's user folder'''
134-
return filter(Path.is_dir, _THONNY_USER_PATH.iterdir())
135-
136-
137132
def is_valid_jdk_version(jdk_version: str) -> bool:
138133
'''Check if JDK version meets minimum version requirement.'''
139134
return jdk_version.isdigit() and int(jdk_version) >= _REQUIRE_JDK
140135

141136

142-
def is_valid_jdk_path(jdk_path: PurePath | str) -> bool:
137+
def is_valid_jdk_path(jdk_path: StrPath) -> bool:
143138
'''Check if the given path points to a JDK install with a usable Java.'''
144139
java_compiler = jdk._IS_WINDOWS and 'javac.exe' or 'javac'
145140
return Path(jdk_path, 'bin', java_compiler).is_file()
146141

147142

143+
def get_all_thonny_folders() -> list[str]:
144+
"""Return reverse-sorted names of subfolders within Thonny's user folder."""
145+
with scandir(THONNY_USER_DIR) as entries:
146+
return sorted((e.name for e in entries if e.is_dir()), reverse=True)
147+
148+
148149
class DownloadJDK(Thread):
149150
'''Background thread for downloading & installing JDK into Thonny's folder.
150151
@@ -155,20 +156,40 @@ class DownloadJDK(Thread):
155156
'''
156157
def run(self):
157158
'''Download and setup JDK (installs to Thonny's config directory)'''
158-
for path in get_all_thonny_folder_paths():
159-
# Delete existing Thonny's JDK subfolders matching jdk-<version##>:
160-
if path.name.startswith(_JDK_DIR): shutil.rmtree(path)
159+
# Delete existing Thonny's JDK subfolders matching jdk-<version##>:
160+
self.process_match_jdk_dirs(shutil.rmtree)
161161

162162
# Download and extract JDK subfolder into Thonny's user folder:
163163
jdk.install(_VERSION_JDK, path=THONNY_USER_DIR)
164164

165-
for path in get_all_thonny_folder_paths():
166-
# Rename extracted Thonny's JDK subfolder to jdk-<version##>:
167-
if path.name.startswith(_JDK_DIR): rename(path, _JDK_PATH); break
165+
# Rename extracted Thonny's JDK subfolder to jdk-<version##>:
166+
self.process_match_jdk_dirs(self.rename_folder, True)
168167

169168
set_java_home(_JDK_HOME) # Add a Thonny's JAVA_HOME entry for it
170169

171170

171+
@staticmethod
172+
def process_match_jdk_dirs(action: PathAction, only_1st=False):
173+
'''Apply an action to JDK-matching subfolders in Thonny's folder.'''
174+
for path in DownloadJDK.get_all_thonny_folder_paths():
175+
if path.name.startswith(_JDK_DIR): # Folder name matches <jdk-##>
176+
action(path) # Callback to run on each matching folder path
177+
if only_1st: break # Stop at 1st match occurrence
178+
179+
180+
@staticmethod
181+
def get_all_thonny_folder_paths() -> Iterator[Path]:
182+
'''Find all subfolder paths within Thonny's user folder'''
183+
return filter(Path.is_dir, _THONNY_USER_PATH.iterdir())
184+
185+
186+
@staticmethod
187+
def rename_folder(path: StrPath):
188+
'''Rename a JDK subfolder to the expected jdk-<version##> format.'''
189+
rename(path, _JDK_PATH)
190+
191+
192+
172193
class JdkDialog(ui_utils.CommonDialog):
173194
'''User-facing dialog prompting install of required JDK for py5 sketches.
174195

0 commit comments

Comments
 (0)