1717
1818from __future__ import annotations
1919
20+ import argparse
21+ import os
2022import shutil
2123import subprocess
2224import sys
2325import tempfile
2426from pathlib import Path
2527
2628
27- def run_secure_build (root_path : str | None = None ) -> None :
29+ def run_secure_build (
30+ root_path : str | None = None , prebuild_command : str | None = None
31+ ) -> None :
2832 """Run a secure build of the Python package.
2933
3034 Args:
3135 root_path: Path to the root directory of the Git repository. If None,
3236 the function will take the current working directory as the root.
37+ prebuild_command: Optional command to run before building. This is useful
38+ for compiling translations or other pre-build tasks. The command is
39+ executed in the temporary build directory.
3340
3441 This function performs the following steps:
3542
3643 1. Creates a temporary directory to hold the build files.
3744 2. Creates a tar archive of the current HEAD of the Git repository.
3845 3. Extracts the contents of the tar archive into the temporary directory.
3946 4. Checks for the presence of `pyproject.toml` in the extracted files.
40- 5. Runs the build process using `build` to create source distribution and wheels.
41- 6. Copies the generated files to the `dist/` directory in repository root.
47+ 5. Runs the optional prebuild command if provided.
48+ 6. Runs the build process using `build` to create source distribution and wheels.
49+ 7. Copies the generated files to the `dist/` directory in repository root.
4250
4351 Raises:
4452 RuntimeError: If the current directory is not a Git repository and no
@@ -91,15 +99,42 @@ def run_secure_build(root_path: str | None = None) -> None:
9199 for path in sorted (build_root .iterdir ()):
92100 print (f" - { path .name } " )
93101
94- # Step 4 : run the package build
102+ # Step 4 : run the optional prebuild command
103+ if prebuild_command :
104+ # Replace 'python' with the current interpreter to avoid PATH issues
105+ if prebuild_command .startswith ("python " ):
106+ prebuild_command = f'"{ sys .executable } " { prebuild_command [7 :]} '
107+ elif prebuild_command .startswith ("python3 " ):
108+ prebuild_command = f'"{ sys .executable } " { prebuild_command [8 :]} '
109+
110+ # Prepare environment with absolute PYTHONPATH (relative paths break in
111+ # temp directory)
112+ env = os .environ .copy ()
113+ if "PYTHONPATH" in env :
114+ pythonpath_entries = env ["PYTHONPATH" ].split (os .pathsep )
115+ abs_entries = [
116+ str (Path (entry ).resolve ()) for entry in pythonpath_entries
117+ ]
118+ env ["PYTHONPATH" ] = os .pathsep .join (abs_entries )
119+
120+ print (f"🔧 Running prebuild command: { prebuild_command } " )
121+ subprocess .run (
122+ prebuild_command ,
123+ cwd = build_root ,
124+ check = True ,
125+ shell = True ,
126+ env = env ,
127+ )
128+
129+ # Step 5 : run the package build
95130 print ("🔨 Building the package..." )
96131 subprocess .run (
97132 [sys .executable , "-m" , "build" , "--sdist" , "--wheel" ],
98133 cwd = build_root ,
99134 check = True ,
100135 )
101136
102- # Step 5 : copy the artifacts to dist/
137+ # Step 6 : copy the artifacts to dist/
103138 print (f"📦 Copying built packages to { dist_dir } ..." )
104139 build_dist = build_root / "dist"
105140 dist_dir .mkdir (exist_ok = True )
@@ -110,4 +145,22 @@ def run_secure_build(root_path: str | None = None) -> None:
110145
111146
112147if __name__ == "__main__" :
113- run_secure_build ()
148+ parser = argparse .ArgumentParser (
149+ description = "Securely build Python packages from a Git repository."
150+ )
151+ parser .add_argument (
152+ "--prebuild" ,
153+ type = str ,
154+ default = None ,
155+ help = "Command to run before building (e.g., to compile translations). "
156+ "The command is executed in the temporary build directory." ,
157+ )
158+ parser .add_argument (
159+ "root_path" ,
160+ nargs = "?" ,
161+ default = None ,
162+ help = "Path to the root directory of the Git repository. "
163+ "If not provided, the current working directory is used." ,
164+ )
165+ args = parser .parse_args ()
166+ run_secure_build (root_path = args .root_path , prebuild_command = args .prebuild )
0 commit comments