@@ -114,6 +114,66 @@ def build_python_framework(self, target_dir):
114114 self .output (results , verbose_level = 2 )
115115 return dest
116116
117+ def install_sitecustomize (self , framework_path ):
118+ """Write sitecustomize.py so OpenSSL finds certifi's CA bundle after relocation."""
119+ major_minor = "." .join (self .env ["python_version" ].split ("." )[:2 ])
120+ site_packages = os .path .join (
121+ framework_path ,
122+ "Versions" ,
123+ major_minor ,
124+ "lib" ,
125+ f"python{ major_minor } " ,
126+ "site-packages" ,
127+ )
128+ sitecustomize_path = os .path .join (site_packages , "sitecustomize.py" )
129+ if os .path .exists (sitecustomize_path ):
130+ self .output (
131+ f"sitecustomize.py already exists at { sitecustomize_path } ; skipping"
132+ )
133+ return
134+ # OpenSSL's compiled-in CA path doesn't exist after relocation; point at certifi.
135+ content = """\
136+ import os
137+
138+
139+ def _ssl_cert_file_is_valid():
140+ path = os.environ.get('SSL_CERT_FILE')
141+ return bool(path) and os.path.isfile(path)
142+
143+
144+ if not _ssl_cert_file_is_valid():
145+ try:
146+ import certifi
147+ except ImportError:
148+ pass
149+ else:
150+ os.environ['SSL_CERT_FILE'] = certifi.where()
151+ """
152+ with open (sitecustomize_path , "w" ) as f :
153+ f .write (content )
154+ self .output (f"Installed sitecustomize.py at { sitecustomize_path } " )
155+
156+ def smoke_test_https (self , framework_path ):
157+ """Verify that urllib HTTPS works from the built framework."""
158+ major_minor = "." .join (self .env ["python_version" ].split ("." )[:2 ])
159+ python_bin = os .path .join (
160+ framework_path , "Versions" , major_minor , "bin" , f"python{ major_minor } "
161+ )
162+ self .output ("Smoke-testing HTTPS from built framework..." )
163+ try :
164+ subprocess .run (
165+ [
166+ python_bin ,
167+ "-c" ,
168+ "import urllib.request; urllib.request.urlopen('https://example.com')" ,
169+ ],
170+ timeout = 30 ,
171+ check = True ,
172+ )
173+ except subprocess .CalledProcessError as e :
174+ raise ProcessorError (f"HTTPS smoke test failed: { e } " )
175+ self .output ("HTTPS smoke test passed." )
176+
117177 def main (self ):
118178 target_dir = os .path .join (self .env ["RECIPE_CACHE_DIR" ], "relocatable-python" )
119179 # Clone the relocatable python repo
@@ -122,6 +182,8 @@ def main(self):
122182 framework_path = self .build_python_framework (target_dir )
123183 if os .path .exists (framework_path ):
124184 self .output (f"Framework built at { framework_path } " )
185+ self .install_sitecustomize (framework_path )
186+ self .smoke_test_https (framework_path )
125187 self .env ["python_path" ] = framework_path
126188 else :
127189 raise ProcessorError (f"Framework not found at path { framework_path } " )
0 commit comments