import setuptools, importlib, subprocess, os, re def write_metafile(metadata, filename): try: os.makedirs(filename[:-10]) except FileExistsError: pass with open(filename, 'w') as f: f.write(metadata) def generate_metafile(setup_dict, path): metadata = ( '{{% set name = "{name}" %}}\n' '{{% set version = "{version}" %}}\n' '\n' 'package:\n' ' name: "{{{{ name|lower }}}}"\n' ' version: "{{{{ version }}}}"\n' '\n' 'build:\n' ).format( name=setup_dict["name"], version=setup_dict["version"] ) if 'entry_points' in setup_dict.keys(): metadata += ' entry_points:\n' for ep in setup_dict['entry_points']: metadata += ' - {}\n'.format(ep) metadata += (' script: {{{{PYTHON}}}} setup.py install\n' '\n' 'source:\n' ' path: {}\n'.format(path)) metadata += '\n' if 'install_requires' in setup_dict.keys(): metadata += 'requirements:\n' build_reqs = ' build:\n' run_reqs = ' run:\n' for req in setup_dict['install_requires'].split(', '): build_reqs += ' - {}\n'.format(req) run_reqs += ' - {}\n'.format(req) metadata += build_reqs metadata += run_reqs if 'tests_require' in setup_dict.keys(): metadata += ('test:\n' ' source_files:\n' ' - test/\n' ' requires:\n') for req in setup_dict['tests_require'].split(', '): metadata += ' - {}\n'.format(req) metadata += (' commands:\n' ' - pytest -vv --log-level=DEBUG --showlocals\n') metadata += ('\n' 'about:\n' ' license: "{0}"\n' ' license_family: "{0}"\n' ' summary: "{1}"'.format(setup_dict['license'], setup_dict['description'])) return metadata def data_to_dict(setup_data): data_dict = {} r_entry = r"([a-z-_]+): " r_id = r"[a-zA-Z0-9-_]" r_ep = r"{{(?:[a-zA-Z0-9-_.]+):\s*(?P<values>(?:{0}+\s*=\s*[a-zA-Z0-9-_.]+:{0}+(?:,\s*)?)*)}}".format(r_id) for d in setup_data: result = re.match(r_entry, d) if result: substrings = [result.group(0), '[', ']', '\'', '"'] field = result.group(1) value = del_substrings(d, substrings) if value == "None": continue if re.match(r_ep, value): # Parse entry points value = re.match(r_ep, value).group('values') value = re.split(',\s*', value) data_dict[field] = value # print("{}: {}".format(field, value)) return data_dict def get_outputs(names): outputs = [] for name in names: outputs.append("support/conda/{}/meta.yaml".format(name)) return outputs def get_dirs(): find = subprocess.run(['find', '.', '-name', 'setup.py'], stdout=subprocess.PIPE) dirs = find.stdout.decode('utf-8').split('\n') for i, d in enumerate(dirs): if d.find("./src") >= 0: dirs.remove(d) continue dirs[i] = d.replace('/setup.py', '') return dirs def get_names(dirs): names = [] for d in dirs: if d != '': name = d.split('/')[-1] if name == "archive": # Case with ./services/archive having special dir structure name = "services" names.append(name) return names def del_substrings(s, substrings): for replace in substrings: s = s.replace(replace, '') return s class Recipe: def __init__(self, buildout, name, options): self.dirs = get_dirs() self.names = get_names(self.dirs) self.outputs = get_outputs(self.names) self.options = options # TODO: Keep track of path in setup_dict def install(self): root = os.getcwd() for i, d in enumerate(self.dirs): if d != '': os.chdir(d) proc = subprocess.run(['python3', 'parse_setup.py'], stdout=subprocess.PIPE) os.chdir(root) setup_data = (proc.stdout.decode('utf-8')).split('\n') data_dict = data_to_dict(setup_data) metadata = generate_metafile(data_dict, d) write_metafile(metadata, self.outputs[i]) self.options.created(self.outputs[i]) return self.options.created() update = install