12
12
from pathlib import Path
13
13
from wppm import wppm , utils
14
14
15
- # Define constant paths for clarity
16
15
PORTABLE_DIRECTORY = Path (__file__ ).parent / "portable"
17
16
assert PORTABLE_DIRECTORY .is_dir (), f"Portable directory not found: { PORTABLE_DIRECTORY } "
18
17
@@ -35,8 +34,7 @@ def copy_items(source_directories: list[Path], target_directory: Path, verbose:
35
34
36
35
def parse_list_argument (argument_value : str | list [str ], separator = " " ) -> list [str ]:
37
36
"""Parse a separated list argument into a list of strings."""
38
- if not argument_value :
39
- return []
37
+ if not argument_value : return []
40
38
return argument_value .split (separator ) if isinstance (argument_value , str ) else list (argument_value )
41
39
42
40
class WinPythonDistributionBuilder :
@@ -72,7 +70,7 @@ def __init__(self, build_number: int, release_level: str, target_directory: Path
72
70
def _get_python_zip_file (self ) -> Path :
73
71
"""Finds the Python .zip file in the wheels directory."""
74
72
for source_item in self .wheels_directory .iterdir ():
75
- if re .match (r"(pypy3|python-)([0-9]|[a-zA-Z]|.)* .zip" , source_item .name ):
73
+ if re .match (r"(pypy3|python-).*\ .zip" , source_item .name ):
76
74
return source_item
77
75
raise RuntimeError (f"Could not find Python zip package in { self .wheels_directory } " )
78
76
@@ -86,25 +84,9 @@ def python_full_version(self) -> str:
86
84
"""Retrieves the Python full version string from the distribution."""
87
85
return utils .get_python_long_version (self .distribution .target ) if self .distribution else "0.0.0"
88
86
89
- @property
90
- def python_executable_directory (self ) -> str :
91
- """Returns the directory containing the Python executable."""
92
- if self .winpython_directory :
93
- python_path_directory = self .winpython_directory / self .python_directory_name
94
- return str (python_path_directory ) if python_path_directory .is_dir () else str (self .winpython_directory / self .python_name )
95
- return ""
96
-
97
- @property
98
- def architecture_bits (self ) -> int :
99
- """Returns the architecture (32 or 64 bits) of the distribution."""
100
- return self .distribution .architecture if self .distribution else 64
101
-
102
87
def _print_action (self , text : str ):
103
88
"""Prints an action message with progress indicator."""
104
- if self .verbose :
105
- utils .print_box (text )
106
- else :
107
- print (f"{ text } ... " , end = "" , flush = True )
89
+ utils .print_box (text ) if self .verbose else print (f"{ text } ..." , end = "" , flush = True )
108
90
109
91
def _extract_python_archive (self ):
110
92
"""Extracts the Python zip archive to create the base Python environment."""
@@ -124,33 +106,38 @@ def _copy_essential_files(self):
124
106
self ._print_action (f"Copying tools to { tools_target_directory } " )
125
107
copy_items (self .tools_directories , tools_target_directory , self .verbose )
126
108
127
- def _create_initial_batch_scripts (self ):
128
- """Creates initial batch scripts, including environment setup."""
129
- self ._print_action ("Creating initial batch scripts" )
130
- # Replacements for batch scripts (PyPy compatibility)
131
- executable_name = self .distribution .short_exe if self .distribution else "python.exe" # default to python.exe if distribution is not yet set
132
- init_variables = [('WINPYthon_exe' , executable_name ), ('WINPYthon_subdirectory_name' , self .python_directory_name ), ('WINPYVER' , self .winpython_version_name )]
133
- init_variables += [('WINPYVER2' , f"{ self .python_full_version } .{ self .build_number } " ), ('WINPYFLAVOR' , self .flavor ), ('WINPYARCH' , self .architecture_bits )]
134
- with open (self .winpython_directory / "scripts" / "env.ini" , "w" ) as f :
135
- f .writelines ([f'{ a } ={ b } \n ' for a , b in init_variables ])
109
+ def _create_env_config (self ):
110
+ """Creates environment setup"""
111
+ self ._print_action ("Creating env.ini environment setup" )
112
+ executable_name = self .distribution .short_exe if self .distribution else "python.exe"
113
+ config = {
114
+ "WINPYthon_exe" : executable_name ,
115
+ "WINPYthon_subdirectory_name" : self .python_directory_name ,
116
+ "WINPYVER" : self .winpython_version_name ,
117
+ "WINPYVER2" : f"{ self .python_full_version } .{ self .build_number } " ,
118
+ "WINPYFLAVOR" : self .flavor ,
119
+ "WINPYARCH" : self .distribution .architecture if self .distribution else 64 ,
120
+ }
121
+ env_path = self .winpython_directory / "scripts" / "env.ini"
122
+ env_path .parent .mkdir (parents = True , exist_ok = True )
123
+ print ("zzz env_path" , env_path )
124
+ self ._print_action (f"Creating env.ini environment { env_path } " )
125
+ env_path .write_text ("\n " .join (f"{ k } ={ v } " for k , v in config .items ()))
136
126
137
127
def build (self , winpy_dir : Path = None ):
138
128
"""Make or finalise WinPython distribution in the target directory"""
139
129
print (f"Building WinPython with Python archive: { self .python_zip_file .name } " )
140
- self .winpython_directory = winpy_dir
141
-
130
+ self .winpython_directory = Path (winpy_dir )
142
131
self ._print_action (f"Creating WinPython { self .winpython_directory } base directory" )
143
132
if self .winpython_directory .is_dir () and len (self .winpython_directory .parts )>= 4 :
144
133
shutil .rmtree (self .winpython_directory )
145
- os .makedirs (self .winpython_directory , exist_ok = True )
146
134
# preventive re-Creation of settings directory
147
135
(self .winpython_directory / "settings" / "AppData" / "Roaming" ).mkdir (parents = True , exist_ok = True )
148
- self ._extract_python_archive ()
149
-
150
- self .distribution = wppm .Distribution (self .python_executable_directory , verbose = self .verbose )
151
136
137
+ self ._extract_python_archive ()
138
+ self .distribution = wppm .Distribution (self .winpython_directory / self .python_directory_name , verbose = self .verbose )
152
139
self ._copy_essential_files ()
153
- self ._create_initial_batch_scripts ()
140
+ self ._create_env_config ()
154
141
155
142
def make_all (build_number : int , release_level : str , basedir_wpy : Path = None ,
156
143
verbose : bool = False ,
@@ -170,22 +157,19 @@ def make_all(build_number: int, release_level: str, basedir_wpy: Path = None,
170
157
"""
171
158
assert basedir_wpy is not None , "The *winpython_dirname* directory must be specified"
172
159
173
- tools_dirs_list = parse_list_argument (toolsdirs , "," )
160
+ tools_directories = [ Path ( d ) for d in parse_list_argument (toolsdirs , "," )]
174
161
winpy_dir = Path (basedir_wpy )
175
-
176
162
utils .print_box (f"Making WinPython at { winpy_dir } " )
177
163
os .makedirs (winpy_dir , exist_ok = True )
164
+
178
165
builder = WinPythonDistributionBuilder (
179
166
build_number , release_level , winpy_dir .parent , wheels_directory = source_dirs ,
180
- tools_directories = [Path (d ) for d in tools_dirs_list ],
181
- verbose = verbose ,
182
- flavor = flavor
167
+ tools_directories = tools_directories ,
168
+ verbose = verbose , flavor = flavor
183
169
)
184
- builder .build (winpy_dir = winpy_dir )
185
-
170
+ builder .build (winpy_dir )
186
171
187
172
if __name__ == "__main__" :
188
- # DO create only one Winpython distribution at a time
189
173
make_all (
190
174
build_number = 1 ,
191
175
release_level = "b3" ,
0 commit comments