save work on migration to yaml

This commit is contained in:
Radovan Bast 2016-04-18 17:00:18 +02:00
parent edf1245760
commit 4a20af4af9

209
update.py
View File

@ -51,7 +51,7 @@ def interpolate(d, d_map):
for k, v in d.items(): for k, v in d.items():
if isinstance(v, Mapping): if isinstance(v, Mapping):
d[k] = interpolate(d[k], d_map) d[k] = interpolate(d[k], d_map)
elif not isinstance(v, str) and isinstance(v, Iterable): elif isinstance(v, Iterable) and not isinstance(v, str):
l = [] l = []
for x in v: for x in v:
if isinstance(x, Mapping): if isinstance(x, Mapping):
@ -99,15 +99,14 @@ def fetch_url(src, dst):
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
def parse_yaml(file_name): def parse_yaml(stream):
import yaml import yaml
with open(file_name, 'r') as stream: try:
try: config = yaml.load(stream, yaml.SafeLoader)
config = yaml.load(stream, yaml.SafeLoader) except yaml.YAMLError as exc:
except yaml.YAMLError as exc: print(exc)
print(exc) sys.exit(-1)
sys.exit(-1)
config = interpolate(config, config) config = interpolate(config, config)
return config return config
@ -154,19 +153,13 @@ def gen_cmake_command(config):
s.append(' """') s.append(' """')
s.append(" command = []") s.append(" command = []")
# take care of environment variables for env in extract_list(config, 'export'):
for section in config.sections(): s.append(' command.append({0})'.format(env))
if config.has_option(section, 'export'):
for env in config.get(section, 'export').split('\n'):
s.append(' command.append({0})'.format(env))
s.append(" command.append(arguments['--cmake-executable'])") s.append(" command.append(arguments['--cmake-executable'])")
# take care of cmake definitions for definition in extract_list(config, 'define'):
for section in config.sections(): s.append(' command.append({0})'.format(definition))
if config.has_option(section, 'define'):
for definition in config.get(section, 'define').split('\n'):
s.append(' command.append({0})'.format(definition))
s.append(" command.append('-DCMAKE_BUILD_TYPE={0}'.format(arguments['--type']))") s.append(" command.append('-DCMAKE_BUILD_TYPE={0}'.format(arguments['--type']))")
s.append(" command.append('-G \"{0}\"'.format(arguments['--generator']))") s.append(" command.append('-G \"{0}\"'.format(arguments['--generator']))")
@ -217,12 +210,11 @@ def gen_setup(config, relative_path, setup_script_name):
s.append('\nOptions:') s.append('\nOptions:')
options = [] options = []
for section in config.sections():
if config.has_option(section, 'docopt'): for opt in extract_list(config, 'docopt'):
for opt in config.get(section, 'docopt').split('\n'): first = opt.split()[0].strip()
first = opt.split()[0].strip() rest = ' '.join(opt.split()[1:]).strip()
rest = ' '.join(opt.split()[1:]).strip() options.append([first, rest])
options.append([first, rest])
options.append(['--type=<TYPE>', 'Set the CMake build type (debug, release, or relwithdeb) [default: release].']) options.append(['--type=<TYPE>', 'Set the CMake build type (debug, release, or relwithdeb) [default: release].'])
options.append(['--generator=<STRING>', 'Set the CMake build system generator [default: Unix Makefiles].']) options.append(['--generator=<STRING>', 'Set the CMake build system generator [default: Unix Makefiles].'])
@ -328,81 +320,98 @@ def prepend_or_set(config, section, option, value, defaults):
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
def extract_list(config, section):
from collections import Iterable
l = []
if 'modules' in config:
for module in config['modules']:
for k, v in module.items():
for x in v:
if section in x:
if isinstance(x[section], Iterable) and not isinstance(x[section], str):
for y in x[section]:
l.append(y)
else:
l.append(x[section])
return l
# ------------------------------------------------------------------------------
def fetch_modules(config, relative_path): def fetch_modules(config, relative_path):
""" """
Assemble modules which will Assemble modules which will
be included in CMakeLists.txt. be included in CMakeLists.txt.
""" """
from collections import Iterable
download_directory = 'downloaded' download_directory = 'downloaded'
if not os.path.exists(download_directory): if not os.path.exists(download_directory):
os.makedirs(download_directory) os.makedirs(download_directory)
l = list(filter(lambda x: config.has_option(x, 'source'), # here we get the list of sources to fetch
config.sections())) sources = extract_list(config, 'source')
n = len(l)
modules = [] modules = []
Module = collections.namedtuple('Module', 'path name') Module = collections.namedtuple('Module', 'path name')
warnings = [] warnings = []
if n > 0: # otherwise division by zero in print_progress_bar if len(sources) > 0: # otherwise division by zero in print_progress_bar
i = 0 print_progress_bar(text='- assembling modules:', done=0, total=len(sources), width=30)
print_progress_bar(text='- assembling modules:', done=0, total=n, width=30) for i, src in enumerate(sources):
for section in config.sections(): module_name = os.path.basename(src)
if config.has_option(section, 'source'): if 'http' in src:
for src in config.get(section, 'source').split('\n'): path = download_directory
module_name = os.path.basename(src) name = 'autocmake_{0}'.format(module_name)
if 'http' in src: dst = os.path.join(download_directory, 'autocmake_{0}'.format(module_name))
path = download_directory fetch_url(src, dst)
name = 'autocmake_{0}'.format(module_name) file_name = dst
dst = os.path.join(download_directory, 'autocmake_{0}'.format(module_name)) fetch_dst_directory = download_directory
fetch_url(src, dst) else:
file_name = dst if os.path.exists(src):
fetch_dst_directory = download_directory path = os.path.dirname(src)
else: name = module_name
if os.path.exists(src): file_name = src
path = os.path.dirname(src) fetch_dst_directory = path
name = module_name else:
file_name = src sys.stderr.write("ERROR: {0} does not exist\n".format(src))
fetch_dst_directory = path sys.exit(-1)
else:
sys.stderr.write("ERROR: {0} does not exist\n".format(src))
sys.exit(-1)
if config.has_option(section, 'override'): # FIXME
defaults = ast.literal_eval(config.get(section, 'override')) # if config.has_option(section, 'override'):
else: # defaults = ast.literal_eval(config.get(section, 'override'))
defaults = {} # else:
# defaults = {}
# we infer config from the module documentation # FIXME
with open(file_name, 'r') as f: # we infer config from the module documentation
parsed_config = parse_cmake_module(f.read(), defaults) # with open(file_name, 'r') as f:
if parsed_config['warning']: # parsed_config = parse_cmake_module(f.read(), defaults)
warnings.append('WARNING from {0}: {1}'.format(module_name, parsed_config['warning'])) # if parsed_config['warning']:
config = prepend_or_set(config, section, 'docopt', parsed_config['docopt'], defaults) # warnings.append('WARNING from {0}: {1}'.format(module_name, parsed_config['warning']))
config = prepend_or_set(config, section, 'define', parsed_config['define'], defaults) # config = prepend_or_set(config, section, 'docopt', parsed_config['docopt'], defaults)
config = prepend_or_set(config, section, 'export', parsed_config['export'], defaults) # config = prepend_or_set(config, section, 'define', parsed_config['define'], defaults)
if parsed_config['fetch']: # config = prepend_or_set(config, section, 'export', parsed_config['export'], defaults)
for src in parsed_config['fetch'].split('\n'): # if parsed_config['fetch']:
dst = os.path.join(fetch_dst_directory, os.path.basename(src)) # for src in parsed_config['fetch'].split('\n'):
fetch_url(src, dst) # dst = os.path.join(fetch_dst_directory, os.path.basename(src))
# fetch_url(src, dst)
modules.append(Module(path=path, name=name)) modules.append(Module(path=path, name=name))
i += 1 print_progress_bar(
print_progress_bar( text='- assembling modules:',
text='- assembling modules:', done=(i + 1),
done=i, total=len(sources),
total=n, width=30
width=30 )
) # FIXME
if config.has_option(section, 'fetch'): # if config.has_option(section, 'fetch'):
# when we fetch directly from autocmake.yml # # when we fetch directly from autocmake.yml
# we download into downloaded/ # # we download into downloaded/
for src in config.get(section, 'fetch').split('\n'): # for src in config.get(section, 'fetch').split('\n'):
dst = os.path.join(download_directory, os.path.basename(src)) # dst = os.path.join(download_directory, os.path.basename(src))
fetch_url(src, dst) # fetch_url(src, dst)
print('') print('')
if warnings != []: if warnings != []:
@ -438,9 +447,9 @@ def main(argv):
if argv[1] == '--self': if argv[1] == '--self':
# update self # update self
if not os.path.isfile('autocmake.yml'): if not os.path.isfile('autocmake.yml'):
print('- fetching example autocmake.yml') # FIXME print('- fetching example autocmake.yml')
fetch_url( fetch_url(
src='{0}/raw/master/example/autocmake.cfg'.format(AUTOCMAKE_GITHUB_URL), src='{0}/raw/master/example/autocmake.yml'.format(AUTOCMAKE_GITHUB_URL),
dst='autocmake.yml' dst='autocmake.yml'
) )
if not os.path.isfile('.gitignore'): if not os.path.isfile('.gitignore'):
@ -471,7 +480,8 @@ def main(argv):
# read config file # read config file
print('- parsing autocmake.yml') print('- parsing autocmake.yml')
config = parse_yaml('autocmake.yml') with open('autocmake.yml', 'r') as stream:
config = parse_yaml(stream)
if 'name' in config: if 'name' in config:
project_name = config['name'] project_name = config['name']
@ -526,7 +536,8 @@ def make_executable(path):
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
def parse_cmake_module(s_in, defaults={}): def parse_cmake_module(s_in):
from collections import Mapping, Iterable
parsed_config = collections.defaultdict(lambda: None) parsed_config = collections.defaultdict(lambda: None)
@ -550,18 +561,15 @@ def parse_cmake_module(s_in, defaults={}):
autocmake_entry = '\n'.join(s_out).split('autocmake.yml configuration::')[1] autocmake_entry = '\n'.join(s_out).split('autocmake.yml configuration::')[1]
autocmake_entry = autocmake_entry.replace('\n ', '\n') autocmake_entry = autocmake_entry.replace('\n ', '\n')
# FIXME
# we prepend a fake section heading so that we can parse it with configparser
autocmake_entry = '[foo]\n' + autocmake_entry
buf = StringIO(autocmake_entry) buf = StringIO(autocmake_entry)
config = ConfigParser(dict_type=collections.OrderedDict) config = parse_yaml(buf)
config.readfp(buf)
for section in config.sections(): for s in ['docopt', 'define', 'export', 'fetch', 'warning']:
for s in ['docopt', 'define', 'export', 'fetch', 'warning']: if s in config:
if config.has_option(section, s): if isinstance(config[s], Iterable) and not isinstance(config[s], str):
parsed_config[s] = config.get(section, s, 0, defaults) parsed_config[s] = [x for x in config[s]]
else:
parsed_config[s] = [config[s]]
return parsed_config return parsed_config
@ -570,16 +578,17 @@ def parse_cmake_module(s_in, defaults={}):
def test_parse_cmake_module(): def test_parse_cmake_module():
s = '''#.rst: s = r'''#.rst:
# #
# Foo ... # Foo ...
# #
# autocmake.yml configuration:: # autocmake.yml configuration::
# #
# docopt: --cxx=<CXX> C++ compiler [default: g++]. # docopt:
# --extra-cxx-flags=<EXTRA_CXXFLAGS> Extra C++ compiler flags [default: '']. # - "--cxx=<CXX> C++ compiler [default: g++]."
# export: 'CXX={0}'.format(arguments['--cxx']) # - "--extra-cxx-flags=<EXTRA_CXXFLAGS> Extra C++ compiler flags [default: '']."
# define: '-DEXTRA_CXXFLAGS="{0}"'.format(arguments['--extra-cxx-flags']) # export: "'CXX={0}'.format(arguments['--cxx'])"
# define: "'-DEXTRA_CXXFLAGS=\"{0}\"'.format(arguments['--extra-cxx-flags'])"
enable_language(CXX) enable_language(CXX)
@ -588,7 +597,7 @@ if(NOT DEFINED CMAKE_C_COMPILER_ID)
endif()''' endif()'''
parsed_config = parse_cmake_module(s) parsed_config = parse_cmake_module(s)
assert parsed_config['docopt'] == "--cxx=<CXX> C++ compiler [default: g++].\n--extra-cxx-flags=<EXTRA_CXXFLAGS> Extra C++ compiler flags [default: '']." assert parsed_config['docopt'] == ["--cxx=<CXX> C++ compiler [default: g++].", "--extra-cxx-flags=<EXTRA_CXXFLAGS> Extra C++ compiler flags [default: '']."]
s = '''#.rst: s = '''#.rst:
# #