Skip to content

Commit

Permalink
Use pickle instead of repr/ast.literal_eval
Browse files Browse the repository at this point in the history
This fixes a crash with objects like`SpecifierSet`
  • Loading branch information
rotu committed Apr 22, 2020
1 parent ebaa914 commit 7cbccfe
Showing 1 changed file with 11 additions and 9 deletions.
20 changes: 11 additions & 9 deletions colcon_python_setup_py/package_identification/python_setup_py.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Copyright 2016-2018 Dirk Thomas
# Licensed under the Apache License, Version 2.0

import ast
import distutils.core
import os
import pickle
from pathlib import Path
import runpy
try:
Expand Down Expand Up @@ -134,11 +134,11 @@ def get_setup_arguments(setup_py):
setuptools.setup = setuptools_setup
except NameError:
pass
# filter out any data which doesn't work with ast.literal_eval
# filter out any data which doesn't serialize
for key, value in list(data.items()):
try:
ast.literal_eval(repr(value))
except SyntaxError:
pickle.dumps(value)
except pickle.PicklingError:
del data[key]
return data

Expand Down Expand Up @@ -237,9 +237,9 @@ def get_setup_arguments_with_context(setup_py, env):
cmd = [sys.executable, '-c', ';'.join(code_lines)]
result = subprocess.run(
cmd, stdout=subprocess.PIPE, env=env, check=True)
output = result.stdout.decode('utf-8')
output = result.stdout

return ast.literal_eval(output)
return pickle.loads(output)


_setup_information_cache = {}
Expand Down Expand Up @@ -269,6 +269,7 @@ def get_setup_information(setup_py, *, env=None):
def _get_setup_information(setup_py, *, env=None):
code_lines = [
'import sys',
'import pickle',
'from distutils.core import run_setup',

'dist = run_setup('
Expand All @@ -293,14 +294,15 @@ def _get_setup_information(setup_py, *, env=None):
# skip values with custom type OrderedSet
" if k not in ('license_files', 'provides_extras')}",

"sys.stdout.buffer.write(repr(data).encode('utf-8'))"]
"pickle.dump(data, sys.stdout)"]


# invoke distutils.core.run_setup() in a separate interpreter
cmd = [
sys.executable, '-c', ';'.join(line.lstrip() for line in code_lines)]
result = subprocess.run(
cmd, stdout=subprocess.PIPE,
cwd=os.path.abspath(str(setup_py.parent)), check=True, env=env)
output = result.stdout.decode('utf-8')
output = result.stdout

return ast.literal_eval(output)
return pickle.loads(output)

0 comments on commit 7cbccfe

Please sign in to comment.