patchmatch-cython 0.1.0__tar.gz

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.
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2025, Teriks
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,13 @@
1
+ include *.py
2
+ include README.md
3
+ include LICENSE
4
+ recursive-include src *.py *.pyx
5
+ global-exclude *.pyc
6
+ global-exclude *.pyo
7
+ global-exclude *~
8
+ global-exclude .DS_Store
9
+ global-exclude __pycache__
10
+ prune build
11
+ prune dist
12
+ prune .git
13
+ prune .pytest_cache
@@ -0,0 +1,207 @@
1
+ Metadata-Version: 2.4
2
+ Name: patchmatch-cython
3
+ Version: 0.1.0
4
+ Summary: High-performance PatchMatch implementation for image inpainting using Cython
5
+ Home-page: https://github.com/Teriks/patchmatch-cython
6
+ Author: Teriks
7
+ Author-email: Teriks <Teriks999@gmail.com>
8
+ License: BSD 3-Clause License
9
+
10
+ Copyright (c) 2025, Teriks
11
+
12
+ Redistribution and use in source and binary forms, with or without
13
+ modification, are permitted provided that the following conditions are met:
14
+
15
+ 1. Redistributions of source code must retain the above copyright notice, this
16
+ list of conditions and the following disclaimer.
17
+
18
+ 2. Redistributions in binary form must reproduce the above copyright notice,
19
+ this list of conditions and the following disclaimer in the documentation
20
+ and/or other materials provided with the distribution.
21
+
22
+ 3. Neither the name of the copyright holder nor the names of its
23
+ contributors may be used to endorse or promote products derived from
24
+ this software without specific prior written permission.
25
+
26
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
30
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
+ Project-URL: Homepage, https://github.com/Teriks/patchmatch-cython
37
+ Project-URL: Repository, https://github.com/Teriks/patchmatch-cython
38
+ Project-URL: Issues, https://github.com/Teriks/patchmatch-cython/issues
39
+ Keywords: image-processing,inpainting,patchmatch,cython,computer-vision
40
+ Classifier: Development Status :: 4 - Beta
41
+ Classifier: Intended Audience :: Developers
42
+ Classifier: Intended Audience :: Science/Research
43
+ Classifier: Programming Language :: Python :: 3
44
+ Classifier: Programming Language :: Python :: 3.10
45
+ Classifier: Programming Language :: Python :: 3.11
46
+ Classifier: Programming Language :: Python :: 3.12
47
+ Classifier: Programming Language :: Python :: 3.13
48
+ Classifier: Programming Language :: Cython
49
+ Classifier: Topic :: Scientific/Engineering :: Image Processing
50
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
51
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
52
+ Requires-Python: >=3.10
53
+ Description-Content-Type: text/markdown
54
+ License-File: LICENSE
55
+ Requires-Dist: numpy>=1.21.0
56
+ Provides-Extra: visualization
57
+ Requires-Dist: matplotlib>=3.5.0; extra == "visualization"
58
+ Requires-Dist: Pillow>=8.0.0; extra == "visualization"
59
+ Provides-Extra: dev
60
+ Requires-Dist: pytest>=6.0.0; extra == "dev"
61
+ Requires-Dist: build>=0.8.0; extra == "dev"
62
+ Requires-Dist: setuptools>=61.0; extra == "dev"
63
+ Requires-Dist: wheel; extra == "dev"
64
+ Requires-Dist: Cython>=0.29.0; extra == "dev"
65
+ Dynamic: author
66
+ Dynamic: home-page
67
+ Dynamic: license-file
68
+ Dynamic: requires-python
69
+
70
+ # PatchMatch Cython
71
+
72
+ High-performance PatchMatch implementation for pyramidical image inpainting in cython.
73
+
74
+ This package can function without `python-opencv` / `python-opencv-headless` with only slightly reduced quality.
75
+
76
+ Installing OpenCV results in this packaging using it for upsampling (`INTER_LINEAR`).
77
+
78
+ When OpenCV is not installed, an implementation of bilinear upscaling using numpy will be used.
79
+
80
+ This package provides a pure python solver and a cython solver, the cython solver is
81
+ around 30 to 50 times faster than the python solver depending on patch size.
82
+
83
+ ## Installation
84
+
85
+ ```bash
86
+ pip install patchmatch-cython
87
+ ```
88
+
89
+ **From source:**
90
+ ```bash
91
+ git clone <repository-url>
92
+ cd patchmatch-cython
93
+ pip install .
94
+ ```
95
+
96
+ ## Usage
97
+
98
+ ### With OpenCV
99
+
100
+ ```python
101
+ import cv2
102
+ from patchmatch_cython import inpaint_pyramid
103
+
104
+ # Load image and mask
105
+ image = cv2.imread('image.jpg')
106
+ mask = cv2.imread('mask.png', 0) > 128
107
+
108
+ # Inpaint
109
+ result = inpaint_pyramid(image, mask)
110
+
111
+ cv2.imwrite('result.jpg', result)
112
+ ```
113
+
114
+ ### With Pillow
115
+
116
+ ```python
117
+ import numpy as np
118
+ from PIL import Image
119
+ from patchmatch_cython import inpaint_pyramid
120
+
121
+ # Load image and mask
122
+ image = np.array(Image.open('image.jpg'))
123
+ mask = np.array(Image.open('mask.png').convert('L')) > 128
124
+
125
+ # Inpaint (auto-selects fastest available solver)
126
+ result = inpaint_pyramid(image, mask)
127
+
128
+ Image.fromarray(result).save('result.jpg')
129
+ ```
130
+
131
+ ### Explicit Solver Selection
132
+
133
+ ```python
134
+ from patchmatch_cython import PythonSolver, CythonSolver, inpaint_pyramid
135
+
136
+ # Force specific solver
137
+ result = inpaint_pyramid(image, mask, solver_class=CythonSolver) # Fast
138
+ result = inpaint_pyramid(image, mask, solver_class=PythonSolver) # Fallback
139
+ ```
140
+
141
+ ## Package Extras
142
+
143
+ **For examples:**
144
+
145
+ ```bash
146
+ pip install patchmatch-cython[visualization]
147
+ ```
148
+
149
+ Adds: `matplotlib`, `Pillow`
150
+
151
+ **For development:**
152
+
153
+ ```bash
154
+ pip install patchmatch-cython[dev]
155
+ ```
156
+
157
+ Adds: `pytest`, `build`, `cibuildwheel`, `setuptools`, `wheel`
158
+
159
+ ## Building
160
+
161
+ To build wheels locally for distribution or development:
162
+
163
+ ### Prerequisites
164
+
165
+ Install build dependencies:
166
+
167
+ ```bash
168
+ pip install cibuildwheel
169
+ ```
170
+
171
+ ### Build Wheels
172
+
173
+ Use the included `local_build.py` script to build locally:
174
+
175
+ ```bash
176
+ # Build for all supported Python versions (3.10-3.13)
177
+ python local_build.py
178
+
179
+ # Build for specific Python versions
180
+ python local_build.py --python 3.11 3.12
181
+
182
+ # Build for specific platform
183
+ python local_build.py --platform linux
184
+
185
+ # Build and test wheel installation
186
+ python local_build.py --test
187
+
188
+ # Build without cleaning previous artifacts
189
+ python local_build.py --no-clean
190
+
191
+ # View all options
192
+ python local_build.py --help
193
+ ```
194
+
195
+ ### Build Options
196
+
197
+ - `--python`: Specify Python versions to build for (e.g., `3.11 3.12`)
198
+ - `--platform`: Target platform (`auto`, `linux`, `macos`, `windows`)
199
+ - `--test`: Test wheel installation after building
200
+ - `--no-clean`: Skip cleaning build artifacts before building
201
+
202
+
203
+ ## Requirements
204
+
205
+ - Python 3.10+
206
+ - NumPy (auto-installed)
207
+ - C++ compiler (for building from source)
@@ -0,0 +1,138 @@
1
+ # PatchMatch Cython
2
+
3
+ High-performance PatchMatch implementation for pyramidical image inpainting in cython.
4
+
5
+ This package can function without `python-opencv` / `python-opencv-headless` with only slightly reduced quality.
6
+
7
+ Installing OpenCV results in this packaging using it for upsampling (`INTER_LINEAR`).
8
+
9
+ When OpenCV is not installed, an implementation of bilinear upscaling using numpy will be used.
10
+
11
+ This package provides a pure python solver and a cython solver, the cython solver is
12
+ around 30 to 50 times faster than the python solver depending on patch size.
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ pip install patchmatch-cython
18
+ ```
19
+
20
+ **From source:**
21
+ ```bash
22
+ git clone <repository-url>
23
+ cd patchmatch-cython
24
+ pip install .
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ### With OpenCV
30
+
31
+ ```python
32
+ import cv2
33
+ from patchmatch_cython import inpaint_pyramid
34
+
35
+ # Load image and mask
36
+ image = cv2.imread('image.jpg')
37
+ mask = cv2.imread('mask.png', 0) > 128
38
+
39
+ # Inpaint
40
+ result = inpaint_pyramid(image, mask)
41
+
42
+ cv2.imwrite('result.jpg', result)
43
+ ```
44
+
45
+ ### With Pillow
46
+
47
+ ```python
48
+ import numpy as np
49
+ from PIL import Image
50
+ from patchmatch_cython import inpaint_pyramid
51
+
52
+ # Load image and mask
53
+ image = np.array(Image.open('image.jpg'))
54
+ mask = np.array(Image.open('mask.png').convert('L')) > 128
55
+
56
+ # Inpaint (auto-selects fastest available solver)
57
+ result = inpaint_pyramid(image, mask)
58
+
59
+ Image.fromarray(result).save('result.jpg')
60
+ ```
61
+
62
+ ### Explicit Solver Selection
63
+
64
+ ```python
65
+ from patchmatch_cython import PythonSolver, CythonSolver, inpaint_pyramid
66
+
67
+ # Force specific solver
68
+ result = inpaint_pyramid(image, mask, solver_class=CythonSolver) # Fast
69
+ result = inpaint_pyramid(image, mask, solver_class=PythonSolver) # Fallback
70
+ ```
71
+
72
+ ## Package Extras
73
+
74
+ **For examples:**
75
+
76
+ ```bash
77
+ pip install patchmatch-cython[visualization]
78
+ ```
79
+
80
+ Adds: `matplotlib`, `Pillow`
81
+
82
+ **For development:**
83
+
84
+ ```bash
85
+ pip install patchmatch-cython[dev]
86
+ ```
87
+
88
+ Adds: `pytest`, `build`, `cibuildwheel`, `setuptools`, `wheel`
89
+
90
+ ## Building
91
+
92
+ To build wheels locally for distribution or development:
93
+
94
+ ### Prerequisites
95
+
96
+ Install build dependencies:
97
+
98
+ ```bash
99
+ pip install cibuildwheel
100
+ ```
101
+
102
+ ### Build Wheels
103
+
104
+ Use the included `local_build.py` script to build locally:
105
+
106
+ ```bash
107
+ # Build for all supported Python versions (3.10-3.13)
108
+ python local_build.py
109
+
110
+ # Build for specific Python versions
111
+ python local_build.py --python 3.11 3.12
112
+
113
+ # Build for specific platform
114
+ python local_build.py --platform linux
115
+
116
+ # Build and test wheel installation
117
+ python local_build.py --test
118
+
119
+ # Build without cleaning previous artifacts
120
+ python local_build.py --no-clean
121
+
122
+ # View all options
123
+ python local_build.py --help
124
+ ```
125
+
126
+ ### Build Options
127
+
128
+ - `--python`: Specify Python versions to build for (e.g., `3.11 3.12`)
129
+ - `--platform`: Target platform (`auto`, `linux`, `macos`, `windows`)
130
+ - `--test`: Test wheel installation after building
131
+ - `--no-clean`: Skip cleaning build artifacts before building
132
+
133
+
134
+ ## Requirements
135
+
136
+ - Python 3.10+
137
+ - NumPy (auto-installed)
138
+ - C++ compiler (for building from source)
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Local wheel building script
4
+
5
+ This script builds wheels for all supported Python versions using cibuildwheel.
6
+ """
7
+
8
+ import os
9
+ import sys
10
+ import subprocess
11
+ import shutil
12
+ import argparse
13
+ from pathlib import Path
14
+
15
+ def run_command(cmd, env=None):
16
+ """Run command and return success status"""
17
+ print(f"RUNNING: {cmd}")
18
+ try:
19
+ result = subprocess.run(cmd, shell=True, check=True, env=env)
20
+ return True
21
+ except subprocess.CalledProcessError as e:
22
+ print(f"ERROR: Command failed with exit code {e.returncode}")
23
+ return False
24
+
25
+ def clean_build_artifacts():
26
+ """Clean previous build artifacts"""
27
+ artifacts_to_clean = [
28
+ "wheelhouse",
29
+ "build",
30
+ "dist",
31
+ "*.egg-info",
32
+ "src/**/*.cpp",
33
+ "src/**/*.c",
34
+ "src/**/*.so",
35
+ "src/**/*.pyd",
36
+ ]
37
+
38
+ print("Cleaning previous build artifacts...")
39
+ for pattern in artifacts_to_clean:
40
+ if '*' in pattern:
41
+ # Handle glob patterns
42
+ import glob
43
+ for path in glob.glob(pattern, recursive=True):
44
+ if os.path.isdir(path):
45
+ print(f" Removing directory: {path}")
46
+ shutil.rmtree(path, ignore_errors=True)
47
+ else:
48
+ print(f" Removing file: {path}")
49
+ os.remove(path)
50
+ else:
51
+ path = Path(pattern)
52
+ if path.exists():
53
+ if path.is_dir():
54
+ print(f" Removing directory: {path}")
55
+ shutil.rmtree(path)
56
+ else:
57
+ print(f" Removing file: {path}")
58
+ path.unlink()
59
+
60
+ def build_wheels(python_versions=None, platforms=None, clean=True):
61
+ """Build wheels using cibuildwheel"""
62
+
63
+ if clean:
64
+ clean_build_artifacts()
65
+
66
+ # Create custom environment
67
+ env = os.environ.copy()
68
+
69
+ # Set build configuration
70
+ if python_versions:
71
+ # Build specific Python versions
72
+ if isinstance(python_versions, list):
73
+ build_pattern = " ".join([f"cp{v.replace('.', '')}-*" for v in python_versions])
74
+ else:
75
+ build_pattern = f"cp{python_versions.replace('.', '')}-*"
76
+ env["CIBW_BUILD"] = build_pattern
77
+ print(f"Building for Python versions: {python_versions}")
78
+ else:
79
+ # Build all supported versions (default)
80
+ env["CIBW_BUILD"] = "cp310-* cp311-* cp312-* cp313-*"
81
+ print("Building for all supported Python versions (3.10-3.13)")
82
+
83
+
84
+
85
+ # Set platform-specific configurations
86
+ if platforms:
87
+ if isinstance(platforms, list):
88
+ platform_arg = f"--platform {' '.join(platforms)}"
89
+ else:
90
+ platform_arg = f"--platform {platforms}"
91
+ else:
92
+ platform_arg = "" # Build for current platform
93
+
94
+ # Configure test command
95
+ env["CIBW_TEST_COMMAND"] = "python -c \"import patchmatch_cython; print('Import successful')\""
96
+
97
+ print(f"\n{'='*70}")
98
+ print("BUILDING WHEELS")
99
+ print(f"{'='*70}")
100
+
101
+ # Run cibuildwheel
102
+ cmd = f"cibuildwheel --output-dir wheelhouse {platform_arg}".strip()
103
+ success = run_command(cmd, env)
104
+
105
+ if not success:
106
+ # Try as Python module
107
+ cmd = f"{sys.executable} -m cibuildwheel --output-dir wheelhouse {platform_arg}".strip()
108
+ success = run_command(cmd, env)
109
+
110
+ if success:
111
+ print(f"\n{'='*70}")
112
+ print("BUILD SUCCESSFUL")
113
+ print(f"{'='*70}")
114
+
115
+ # List built wheels
116
+ wheelhouse = Path("wheelhouse")
117
+ if wheelhouse.exists():
118
+ wheels = list(wheelhouse.glob("*.whl"))
119
+ print(f"\nBuilt {len(wheels)} wheels:")
120
+ for wheel in wheels:
121
+ size_mb = wheel.stat().st_size / (1024 * 1024)
122
+ print(f" WHEEL: {wheel.name} ({size_mb:.1f} MB)")
123
+
124
+ return True
125
+ else:
126
+ print(f"\n{'='*70}")
127
+ print("BUILD FAILED")
128
+ print(f"{'='*70}")
129
+ return False
130
+
131
+ def validate_wheel_installation():
132
+ """Test installing and importing built wheels"""
133
+ wheelhouse = Path("wheelhouse")
134
+ wheels = list(wheelhouse.glob("*.whl"))
135
+
136
+ if not wheels:
137
+ print("ERROR: No wheels found to test")
138
+ return False
139
+
140
+ print(f"\n{'='*70}")
141
+ print("TESTING WHEEL INSTALLATION")
142
+ print(f"{'='*70}")
143
+
144
+ # Test the first wheel
145
+ wheel = wheels[0]
146
+ print(f"Testing wheel: {wheel.name}")
147
+
148
+ # Install wheel in a temporary way
149
+ test_cmd = f"pip install {wheel} --force-reinstall --no-deps"
150
+ if run_command(test_cmd):
151
+ # Test import
152
+ test_import = "python -c \"import patchmatch_cython; print('SUCCESS: Import successful')\""
153
+ if run_command(test_import):
154
+ print("SUCCESS: Wheel installation and import test passed")
155
+ return True
156
+
157
+ print("ERROR: Wheel installation test failed")
158
+ return False
159
+
160
+ def main():
161
+ """Main function"""
162
+ parser = argparse.ArgumentParser(description="Build wheels for patchmatch-cython")
163
+ parser.add_argument("--python", nargs="*",
164
+ help="Python versions to build for (e.g., 3.11 3.12). Default: all supported versions")
165
+ parser.add_argument("--platform", choices=["auto", "linux", "macos", "windows"],
166
+ help="Platform to build for. Default: current platform")
167
+ parser.add_argument("--no-clean", action="store_true",
168
+ help="Don't clean build artifacts before building")
169
+ parser.add_argument("--test", action="store_true",
170
+ help="Test wheel installation after building")
171
+
172
+ args = parser.parse_args()
173
+
174
+ print("PatchMatch Cython - Local Wheel Builder")
175
+ print("=" * 70)
176
+
177
+ # Check if cibuildwheel is installed
178
+ print("Checking for cibuildwheel...")
179
+ cibw_found = False
180
+
181
+ # Try importing cibuildwheel as a Python module first (most reliable)
182
+ try:
183
+ import cibuildwheel
184
+ print(f"SUCCESS: Found cibuildwheel module version: {cibuildwheel.__version__}")
185
+ cibw_found = True
186
+ except ImportError:
187
+ print("cibuildwheel module not importable, trying command line...")
188
+
189
+ # Try as a direct command with --help
190
+ try:
191
+ result = subprocess.run(["cibuildwheel", "--help"], check=True, capture_output=True, text=True)
192
+ print("SUCCESS: Found cibuildwheel (direct command)")
193
+ cibw_found = True
194
+ except subprocess.CalledProcessError as e:
195
+ print(f"Direct command failed with exit code {e.returncode}")
196
+ except FileNotFoundError:
197
+ print("Direct command not found")
198
+
199
+ # Try as a Python module with --help
200
+ if not cibw_found:
201
+ try:
202
+ result = subprocess.run([sys.executable, "-m", "cibuildwheel", "--help"], check=True, capture_output=True, text=True)
203
+ print("SUCCESS: Found cibuildwheel (Python module)")
204
+ cibw_found = True
205
+ except subprocess.CalledProcessError as e:
206
+ print(f"Python module failed with exit code {e.returncode}")
207
+ except FileNotFoundError:
208
+ print("Python module not found")
209
+
210
+ if not cibw_found:
211
+ print("ERROR: cibuildwheel not found. Install with: pip install cibuildwheel")
212
+ return 1
213
+
214
+ # Check if we're in the right directory
215
+ if not Path("src/patchmatch_cython/cython_solver_impl.pyx").exists():
216
+ print("ERROR: cython_solver_impl.pyx not found in src/patchmatch_cython/. Run from the project root.")
217
+ print("Current directory:", os.getcwd())
218
+ print("Looking for:", Path("src/patchmatch_cython/cython_solver_impl.pyx").absolute())
219
+ return 1
220
+
221
+ print("SUCCESS: Environment checks passed")
222
+
223
+ # Configure build parameters
224
+ python_versions = args.python
225
+ platforms = args.platform
226
+
227
+ # Build wheels
228
+ success = build_wheels(
229
+ python_versions=python_versions,
230
+ platforms=platforms,
231
+ clean=not args.no_clean
232
+ )
233
+
234
+ if not success:
235
+ return 1
236
+
237
+ # Test wheel installation if requested
238
+ if args.test:
239
+ validate_wheel_installation()
240
+
241
+ print(f"\n{'='*70}")
242
+ print("WHEEL BUILDING COMPLETE")
243
+ print(f"{'='*70}")
244
+ print("INFO: Check the 'wheelhouse' directory for built wheels")
245
+
246
+ return 0
247
+
248
+ if __name__ == "__main__":
249
+ sys.exit(main())