def find_projects(basepath, exclude_paths=None, exclude_subspaces=False): """ Crawls the filesystem to find project manifest files and parses them. :param basepath: The path to search in, ``str`` :param exclude_paths: A list of paths which should not be searched, ``list`` :param exclude_subspaces: The flag is subfolders containing a .alpine file should not be searched, ``bool`` :returns: A dict mapping relative paths to ``Project`` objects ``dict`` :raises: :exc:RuntimeError` If multiple projects have the same name """ projects = {} duplicates = {} paths = find_project_paths(basepath, exclude_paths, exclude_subspaces) for path in paths: project = parse_project(os.path.join(basepath, path)) paths_with_same_name = [path_ for path_, pkg in projects.items() if pkg.name == project.name] if paths_with_same_name: if project.name not in duplicates: duplicates[project.name] = paths_with_same_name duplicates[project.name].append(path) projects[path] = project if duplicates: duplicates = ['Multiple projects found with the same name "%s":%s' % (name, ''.join(['\n- %s' % path_ for path_ in paths])) for name, paths in duplicates.items()] raise RuntimeError('\n'.join(duplicates)) return projects
def main(argv=sys.argv[1:]): """ Reads given project_xml and writes extracted variables to outfile. """ parser = argparse.ArgumentParser(description="Read project.xml and write extracted variables to stdout") parser.add_argument('project_xml') parser.add_argument('outfile') args = parser.parse_args(argv) project = parse_project(args.project_xml) lines = _get_output(project) with open(args.outfile, 'w') as ofile: ofile.write('\n'.join(lines))
def test_parse_generated(self): maint = self.get_maintainer() pack = ProjectTemplate(name='bar', format=1, version='0.0.0', abi='pabi', urls=[Url('foo')], description='pdesc', maintainers=[maint], licenses=['BSD']) try: rootdir = tempfile.mkdtemp() file1 = os.path.join(rootdir, 'CMakeLists.txt') file2 = os.path.join(rootdir, PROJECT_MANIFEST_FILENAME) create_project_files(rootdir, pack, 'groovy') self.assertTrue(os.path.isfile(file1)) self.assertTrue(os.path.isfile(file2)) pack_result = parse_project(file2) self.assertEqual(pack.name, pack_result.name) self.assertEqual(pack.format, pack_result.format) self.assertEqual(pack.version, pack_result.version) self.assertEqual(pack.abi, pack_result.abi) self.assertEqual(pack.description, pack_result.description) self.assertEqual(pack.maintainers[0].name, pack_result.maintainers[0].name) self.assertEqual(pack.maintainers[0].email, pack_result.maintainers[0].email) self.assertEqual(pack.authors, pack_result.authors) self.assertEqual(pack.urls[0].url, pack_result.urls[0].url) self.assertEqual('website', pack_result.urls[0].type) self.assertEqual(pack.licenses, pack_result.licenses) self.assertEqual(pack.builddeps, pack_result.builddeps) self.assertEqual(pack.buildtooldeps, pack_result.buildtooldeps) self.assertEqual(pack.rundeps, pack_result.rundeps) self.assertEqual(pack.testdeps, pack_result.testdeps) self.assertEqual(pack.conflicts, pack_result.conflicts) self.assertEqual(pack.replaces, pack_result.replaces) self.assertEqual(pack.exports, pack_result.exports) rdict = generate_distutils_setup(project_xml_path=file2) self.assertEqual({'name': 'bar', 'maintainer': u'John Foo', 'maintainer_email': '*****@*****.**', 'description': 'pdesc', 'license': 'BSD', 'version': '0.0.0', 'author': '', 'url': 'foo'}, rdict) finally: shutil.rmtree(rootdir)
def test_parse_generated_multi(self): # test with multiple attributes filled maint = self.get_maintainer() pack = ProjectTemplate(name='bar', format=1, version='0.0.0', abi='pabi', description='pdesc', maintainers=[maint, maint], authors=[maint, maint], licenses=['BSD', 'MIT'], urls=[Url('foo', 'bugtracker'), Url('bar')], builddeps=[Dependency('dep1')], buildtooldeps=[Dependency('dep2'), Dependency('dep3')], rundeps=[Dependency('dep4')], testdeps=[Dependency('dep5')], conflicts=[Dependency('dep6')], replaces=[Dependency('dep7'), Dependency('dep8')], exports=[Export('architecture_independent'), Export('meta_project')]) def assertEqualDependencies(deplist1, deplist2): if len(deplist1) != len(deplist1): return False for depx, depy in zip(deplist1, deplist2): for attr in ['name', 'lt', 'lte', 'eq', 'gte', 'gt']: if getattr(depx, attr) != getattr(depy, attr): return False return True try: rootdir = tempfile.mkdtemp() file1 = os.path.join(rootdir, 'CMakeLists.txt') file2 = os.path.join(rootdir, PROJECT_MANIFEST_FILENAME) create_project_files(rootdir, pack, 'alpine') self.assertTrue(os.path.isfile(file1)) self.assertTrue(os.path.isfile(file2)) pack_result = parse_project(file2) self.assertEqual(pack.name, pack_result.name) self.assertEqual(pack.format, pack_result.format) self.assertEqual(pack.version, pack_result.version) self.assertEqual(pack.abi, pack_result.abi) self.assertEqual(pack.description, pack_result.description) self.assertEqual(len(pack.maintainers), len(pack_result.maintainers)) self.assertEqual(len(pack.authors), len(pack_result.authors)) self.assertEqual(len(pack.urls), len(pack_result.urls)) self.assertEqual(pack.urls[0].url, pack_result.urls[0].url) self.assertEqual(pack.urls[0].type, pack_result.urls[0].type) self.assertEqual(pack.licenses, pack_result.licenses) self.assertTrue(assertEqualDependencies(pack.builddeps, pack_result.builddeps)) self.assertTrue(assertEqualDependencies(pack.builddeps, pack_result.builddeps)) self.assertTrue(assertEqualDependencies(pack.buildtooldeps, pack_result.buildtooldeps)) self.assertTrue(assertEqualDependencies(pack.rundeps, pack_result.rundeps)) self.assertTrue(assertEqualDependencies(pack.testdeps, pack_result.testdeps)) self.assertTrue(assertEqualDependencies(pack.conflicts, pack_result.conflicts)) self.assertTrue(assertEqualDependencies(pack.replaces, pack_result.replaces)) self.assertEqual(pack.exports[0].tagname, pack_result.exports[0].tagname) self.assertEqual(pack.exports[1].tagname, pack_result.exports[1].tagname) rdict = generate_distutils_setup(project_xml_path=file2) self.assertEqual({'name': 'bar', 'maintainer': u'John Foo <*****@*****.**>, John Foo <*****@*****.**>', 'description': 'pdesc', 'license': 'BSD, MIT', 'version': '0.0.0', 'author': u'John Foo <*****@*****.**>, John Foo <*****@*****.**>', 'url': 'bar'}, rdict) finally: shutil.rmtree(rootdir)
def generate_distutils_setup(project_xml_path=os.path.curdir, **kwargs): """ Extract the information relevant for distutils from the package manifest. The following keys will be set: The "name" and "version" are taken from the eponymous tags. A single maintainer will set the keys "maintainer" and "maintainer_email" while multiple maintainers are merged into the "maintainer" fields (including their emails). Authors are handled likewise. The first URL of type "website" (or without a type) is used for the "url" field. The "description" is taken from the eponymous tag if it does not exceed 200 characters. If it does "description" contains the truncated text while "description_long" contains the complete. All licenses are merged into the "license" field. :param kwargs: All keyword arguments are passed through. The above mentioned keys are verified to be identical if passed as a keyword argument :returns: return dict populated with parsed fields and passed keyword arguments :raises: :exc:`InvalidProject` :raises: :exc:`IOError` """ project = parse_project(project_xml_path) data = {} data['name'] = project.name data['version'] = project.version # either set one author with one email or join all in a single field if len(project.authors) == 1 and project.authors[0].email is not None: data['author'] = project.authors[0].name data['author_email'] = project.authors[0].email else: data['author'] = ', '.join([('%s <%s>' % (a.name, a.email) if a.email is not None else a.name) for a in project.authors]) # either set one maintainer with one email or join all in a single field if len(project.maintainers) == 1: data['maintainer'] = project.maintainers[0].name data['maintainer_email'] = project.maintainers[0].email else: data['maintainer'] = ', '.join(['%s <%s>' % (m.name, m.email) for m in project.maintainers]) # either set the first URL with the type 'website' or the first URL of any type websites = [url.url for url in project.urls if url.type == 'website'] if websites: data['url'] = websites[0] elif project.urls: data['url'] = project.urls[0].url if len(project.description) <= 200: data['description'] = project.description else: data['description'] = project.description[:197] + '...' data['long_description'] = project.description data['license'] = ', '.join(project.licenses) # pass keyword arguments and verify equality if generated and passed in for k, v in kwargs.items(): if k in data: if v != data[k]: raise InvalidProject('The keyword argument "%s" does not match the information from project.xml: "%s" != "%s"' % (k, v, data[k])) else: data[k] = v return data