44
55import multiprocessing
66import os
7+ import traceback
78from typing import Optional
89
910from colcon_core .dependency_descriptor import DependencyDescriptor
@@ -32,24 +33,22 @@ def identify(self, desc): # noqa: D102
3233 if not setup_py .is_file ():
3334 return
3435
35- try :
36- config = get_setup_result (setup_py , env = None )
37- except Exception as e :
38- logger .warning (e )
39- return
36+ # after this point, we are convinced this is a Python package,
37+ # so we should fail with an Exception instead of silently
4038
41- if 'metadata' not in config :
42- return
39+ config = get_setup_result (setup_py , env = None )
4340
4441 name = config ['metadata' ].name
4542 if not name :
46- return
43+ raise RuntimeError (
44+ 'Setup script "{}" returned invalid name {!r}'
45+ .format (setup_py , name ))
4746
4847 desc .type = 'python'
4948 if desc .name is not None and desc .name != name :
50- msg = 'Package name already set to different value'
51- logger . error ( msg )
52- raise RuntimeError ( msg )
49+ raise RuntimeError (
50+ 'Setup script "{}" returned different name {!r} != {!r}'
51+ . format ( setup_py , name , desc . name ) )
5352 desc .name = name
5453
5554 desc .metadata ['version' ] = config ['metadata' ].version
@@ -79,29 +78,25 @@ def get_setup_result(setup_py, *, env: Optional[dict]):
7978
8079 :param setup_py: Path to a setup.py script
8180 :param env: Environment variables to set before running setup.py
82- :return: None or Dictionary of data describing the package.
81+ :return: Dictionary of data describing the package.
82+ :raise: RuntimeError if the setup script encountered an error
8383 """
8484 conn_recv , conn_send = multiprocessing .Pipe (duplex = False )
85- p = multiprocessing .Process (
86- target = _get_setup_result_target ,
87- args = (os .path .abspath (str (setup_py )), env , conn_send )
88- )
89- p .start ()
90- p .join ()
91-
92- if not conn_recv .poll ():
93- raise RuntimeError (
94- 'Python setup script "{}" did not return any data'
95- .format (setup_py ))
96-
97- result_or_error = conn_recv .recv ()
98- conn_recv .close ()
99-
100- if isinstance (result_or_error , dict ):
101- return result_or_error
85+ with conn_send :
86+ p = multiprocessing .Process (
87+ target = _get_setup_result_target ,
88+ args = (os .path .abspath (str (setup_py )), env , conn_send )
89+ )
90+ p .start ()
91+ p .join ()
92+ with conn_recv :
93+ result_or_exc_info = conn_recv .recv ()
94+
95+ if isinstance (result_or_exc_info , dict ):
96+ return result_or_exc_info
10297 raise RuntimeError (
103- 'Python setup script "{}" failed: {!r }'
104- .format (setup_py , result_or_error )) from result_or_error
98+ 'Failure when trying to run setup script {}: \n { }'
99+ .format (setup_py , traceback . format_exception ( * result_or_exc_info )))
105100
106101
107102def _get_setup_result_target (setup_py : str , env : Optional [dict ], conn_send ):
@@ -113,12 +108,12 @@ def _get_setup_result_target(setup_py: str, env: Optional[dict], conn_send):
113108
114109 :param setup_py: Absolute path to a setup.py script
115110 :param env: Environment variables to set before running setup.py
116- :param conn_send: Connection to send the result as either a dict or an
117- Exception.
111+ :param conn_send: Connection to send the result as either a dict or the
112+ result of sys.exc_info
118113 """
114+ import distutils .core
115+ import sys
119116 try :
120- import distutils .core
121-
122117 # need to be in setup.py's parent dir to detect any setup.cfg
123118 os .chdir (os .path .dirname (setup_py ))
124119
@@ -144,10 +139,9 @@ def _get_setup_result_target(setup_py: str, env: Optional[dict], conn_send):
144139 # Private properties
145140 and not attr .startswith ('_' )
146141 )})
147- except Exception as e :
148- conn_send .send (e )
149- finally :
150- conn_send .close ()
142+ except BaseException :
143+ conn_send .send (sys .exc_info ())
144+ raise
151145
152146
153147def create_dependency_descriptor (requirement_string ):
0 commit comments