Skip to content

Commit

Permalink
Expose errors encountered by the setup script
Browse files Browse the repository at this point in the history
  • Loading branch information
rotu committed Aug 27, 2019
1 parent 11d9c77 commit 09eb1d8
Showing 1 changed file with 55 additions and 36 deletions.
91 changes: 55 additions & 36 deletions colcon_core/package_identification/python.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Copyright 2019 Rover RObotics
# Copyright 2016-2019 Dirk Thomas
# Licensed under the Apache License, Version 2.0

Expand Down Expand Up @@ -29,7 +30,11 @@ def identify(self, desc): # noqa: D102
if not setup_py.is_file():
return

config = get_setup_result(setup_py)
try:
config = get_setup_result(setup_py)
except Exception as e:
logger.warning(e)
return

if 'metadata' not in config:
return
Expand Down Expand Up @@ -78,13 +83,19 @@ def get_setup_result(setup_py, env=None):
)
p.start()
p.join()
if p.exitcode:
logger.warning("Python setup script '%s' terminated with exit code %d",
setup_py, p.exitcode)

if not conn_recv.poll():
raise RuntimeError('No results available from Python setup script')
return conn_recv.recv()
raise RuntimeError('Python setup script "%s" did not return any data',
setup_py)

result_or_error = conn_recv.recv()
conn_recv.close()

if isinstance(result_or_error, dict):
return result_or_error
else:
raise RuntimeError('Python setup script "%s" failed"',
setup_py) from result_or_error


def _get_setup_result_target(setup_py, env, conn_send):
Expand All @@ -95,35 +106,43 @@ def _get_setup_result_target(setup_py, env, conn_send):
:param setup_py: path to a setup.py script
:param env: environment variables to set before running setup.py
:param conn_send: Connection to send the results dictionary
:param conn_send: Connection to send the result as either a dict or
an Exception.
:return: None. Results are transmitted via conn_send.
"""
import os
import distutils.core

# need to be in setup.py's parent dir to detect any setup.cfg
os.chdir(os.path.dirname(setup_py))

# don't worry - the environments of functions called with
# subprocess.Process don't leak into each other
if env is not None:
os.environ.update(env)

result = distutils.core.run_setup(str(setup_py), stop_after='commandline')

# could just return all attrs in result.__dict__, but we take this
# opportunity to filter a few things that don't need to be there
conn_send.send({
attr: value for attr, value in result.__dict__.items()
if (
# These *seem* useful but always have the value 0.
# Look for their values in the 'metadata' object instead.
attr not in result.display_option_names
# Getter methods
and not callable(value)
# Private properties
and not attr.startswith('_')
)})
try:
import os
import distutils.core

# need to be in setup.py's parent dir to detect any setup.cfg
os.chdir(os.path.dirname(setup_py))

# don't worry - the environments of functions called with
# subprocess.Process don't leak into each other
if env is not None:
os.environ.update(env)

result = distutils.core.run_setup(
str(setup_py),
stop_after='commandline')

# could just return all attrs in result.__dict__, but we take this
# opportunity to filter a few things that don't need to be there
conn_send.send({
attr: value for attr, value in result.__dict__.items()
if (
# These *seem* useful but always have the value 0.
# Look for their values in the 'metadata' object instead.
attr not in result.display_option_names
# Getter methods
and not callable(value)
# Private properties
and not attr.startswith('_')
)})
except Exception as e:
conn_send.send(e)
finally:
conn_send.close()


def create_dependency_descriptor(requirement_string):
Expand All @@ -141,8 +160,8 @@ def create_dependency_descriptor(requirement_string):
'!=': 'version_neq',
'<=': 'version_lte',
'>=': 'version_gte',
'>': 'version_gt',
'<': 'version_lt',
'>': 'version_gt',
'<': 'version_lt',
}

requirement = parse_requirement(requirement_string)
Expand All @@ -156,7 +175,7 @@ def create_dependency_descriptor(requirement_string):
else:
logger.warn(
"Ignoring unknown symbol '{symbol}' in '{requirement}'"
.format_map(locals()))
.format_map(locals()))
return DependencyDescriptor(requirement.name, metadata=metadata)


Expand Down

0 comments on commit 09eb1d8

Please sign in to comment.