Add recipe_diff function and helpers.
This takes a pair of Recipe objects and returns a list of diff dicts that include what was changed between the two recipes.
This commit is contained in:
		
							parent
							
								
									a76e95dcb5
								
							
						
					
					
						commit
						052a8ba991
					
				| @ -718,3 +718,83 @@ def is_parent_diff(repo, filename, tree, parent): | |||||||
|     diff_opts.set_pathspec([filename]) |     diff_opts.set_pathspec([filename]) | ||||||
|     diff = Git.Diff.new_tree_to_tree(repo, parent.get_tree(), tree, diff_opts) |     diff = Git.Diff.new_tree_to_tree(repo, parent.get_tree(), tree, diff_opts) | ||||||
|     return diff.get_num_deltas() > 0 |     return diff.get_num_deltas() > 0 | ||||||
|  | 
 | ||||||
|  | def find_name(name, lst): | ||||||
|  |     """Find the dict matching the name in a list and return it. | ||||||
|  | 
 | ||||||
|  |     :param name: Name to search for | ||||||
|  |     :type name: str | ||||||
|  |     :param lst: List of dict's with "name" field | ||||||
|  |     :returns: First dict with matching name, or None | ||||||
|  |     :rtype: dict or None | ||||||
|  |     """ | ||||||
|  |     for e in lst: | ||||||
|  |         if e["name"] == name: | ||||||
|  |             return e | ||||||
|  |     return None | ||||||
|  | 
 | ||||||
|  | def diff_items(title, old_items, new_items): | ||||||
|  |     """Return the differences between two lists of dicts. | ||||||
|  | 
 | ||||||
|  |     :param title: Title of the entry | ||||||
|  |     :type title: str | ||||||
|  |     :param old_items: List of item dicts with "name" field | ||||||
|  |     :type old_items: list(dict) | ||||||
|  |     :param new_items: List of item dicts with "name" field | ||||||
|  |     :type new_items: list(dict) | ||||||
|  |     :returns: List of diff dicts with old/new entries | ||||||
|  |     :rtype: list(dict) | ||||||
|  |     """ | ||||||
|  |     diffs = [] | ||||||
|  |     old_names = set(m["name"] for m in old_items) | ||||||
|  |     new_names = set(m["name"] for m in new_items) | ||||||
|  | 
 | ||||||
|  |     added_items = new_names.difference(old_names) | ||||||
|  |     added_items = sorted(added_items, key=lambda n: n.lower()) | ||||||
|  | 
 | ||||||
|  |     removed_items = old_names.difference(new_names) | ||||||
|  |     removed_items = sorted(removed_items, key=lambda n: n.lower()) | ||||||
|  | 
 | ||||||
|  |     same_items = old_names.intersection(new_names) | ||||||
|  |     same_items = sorted(same_items, key=lambda n: n.lower()) | ||||||
|  | 
 | ||||||
|  |     for name in added_items: | ||||||
|  |         diffs.append({"old":None, | ||||||
|  |                       "new":{title:find_name(name, new_items)}}) | ||||||
|  | 
 | ||||||
|  |     for name in removed_items: | ||||||
|  |         diffs.append({"old":{title:find_name(name, old_items)}, | ||||||
|  |                       "new":None}) | ||||||
|  | 
 | ||||||
|  |     for name in same_items: | ||||||
|  |         old_item = find_name(name, old_items) | ||||||
|  |         new_item = find_name(name, new_items) | ||||||
|  |         if old_item != new_item: | ||||||
|  |             diffs.append({"old":{title:old_item}, | ||||||
|  |                           "new":{title:new_item}}) | ||||||
|  | 
 | ||||||
|  |     return diffs | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def recipe_diff(old_recipe, new_recipe): | ||||||
|  |     """Diff two versions of a recipe | ||||||
|  | 
 | ||||||
|  |     :param old_recipe: The old version of the recipe | ||||||
|  |     :type old_recipe: Recipe | ||||||
|  |     :param new_recipe: The new version of the recipe | ||||||
|  |     :type new_recipe: Recipe | ||||||
|  |     :returns: A list of diff dict entries with old/new | ||||||
|  |     :rtype: list(dict) | ||||||
|  |     """ | ||||||
|  | 
 | ||||||
|  |     diffs = [] | ||||||
|  |     # These cannot be added or removed, just different | ||||||
|  |     for element in ["name", "description", "version"]: | ||||||
|  |         if old_recipe[element] != new_recipe[element]: | ||||||
|  |             diffs.append({"old":{element.title():old_recipe[element]}, | ||||||
|  |                           "new":{element.title():new_recipe[element]}}) | ||||||
|  | 
 | ||||||
|  |     diffs.extend(diff_items("Module", old_recipe["modules"], new_recipe["modules"])) | ||||||
|  |     diffs.extend(diff_items("Package", old_recipe["packages"], new_recipe["packages"])) | ||||||
|  | 
 | ||||||
|  |     return diffs | ||||||
|  | |||||||
| @ -39,6 +39,25 @@ class BasicRecipeTest(unittest.TestCase): | |||||||
|                     result_dict = eval(f_dict.read()) |                     result_dict = eval(f_dict.read()) | ||||||
|                 self.input_toml.append((f_toml.read(), result_dict)) |                 self.input_toml.append((f_toml.read(), result_dict)) | ||||||
| 
 | 
 | ||||||
|  |         self.old_modules = [recipes.RecipeModule("toml", "2.1"), | ||||||
|  |                             recipes.RecipeModule("bash", "4.*"), | ||||||
|  |                             recipes.RecipeModule("httpd", "3.7.*")] | ||||||
|  |         self.old_packages = [recipes.RecipePackage("python", "2.7.*"), | ||||||
|  |                              recipes.RecipePackage("parted", "3.2")] | ||||||
|  |         self.new_modules = [recipes.RecipeModule("toml", "2.1"), | ||||||
|  |                             recipes.RecipeModule("httpd", "3.8.*"), | ||||||
|  |                             recipes.RecipeModule("openssh", "2.8.1")] | ||||||
|  |         self.new_packages = [recipes.RecipePackage("python", "2.7.*"), | ||||||
|  |                              recipes.RecipePackage("parted", "3.2"), | ||||||
|  |                              recipes.RecipePackage("git", "2.13.*")] | ||||||
|  |         self.modules_result = [{"new": {"Modules": {"version": "2.8.1", "name": "openssh"}}, | ||||||
|  |                                 "old": None}, | ||||||
|  |                                {"new": None, | ||||||
|  |                                 "old": {"Modules": {"name": "bash", "version": "4.*"}}}, | ||||||
|  |                                {"new": {"Modules": {"version": "3.8.*", "name": "httpd"}}, | ||||||
|  |                                 "old": {"Modules": {"version": "3.7.*", "name": "httpd"}}}] | ||||||
|  |         self.packages_result = [{"new": {"Packages": {"name": "git", "version": "2.13.*"}}, "old": None}] | ||||||
|  | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     def tearDownClass(self): |     def tearDownClass(self): | ||||||
|         pass |         pass | ||||||
| @ -97,6 +116,30 @@ class BasicRecipeTest(unittest.TestCase): | |||||||
|         new_version = recipe.bump_version("0.0.1") |         new_version = recipe.bump_version("0.0.1") | ||||||
|         self.assertEqual(new_version, "0.1.1") |         self.assertEqual(new_version, "0.1.1") | ||||||
| 
 | 
 | ||||||
|  |     def find_name_test(self): | ||||||
|  |         """Test the find_name function""" | ||||||
|  |         test_list = [{"name":"dog"}, {"name":"cat"}, {"name":"squirrel"}] | ||||||
|  | 
 | ||||||
|  |         self.assertEqual(recipes.find_name("dog", test_list), {"name":"dog"}) | ||||||
|  |         self.assertEqual(recipes.find_name("cat", test_list), {"name":"cat"}) | ||||||
|  |         self.assertEqual(recipes.find_name("squirrel", test_list), {"name":"squirrel"}) | ||||||
|  | 
 | ||||||
|  |     def diff_items_test(self): | ||||||
|  |         """Test the diff_items function""" | ||||||
|  |         self.assertEqual(recipes.diff_items("Modules", self.old_modules, self.new_modules), self.modules_result) | ||||||
|  |         self.assertEqual(recipes.diff_items("Packages", self.old_packages, self.new_packages), self.packages_result) | ||||||
|  | 
 | ||||||
|  |     def recipe_diff_test(self): | ||||||
|  |         """Test the recipe_diff function""" | ||||||
|  |         old_recipe = recipes.Recipe("test-recipe", "A recipe used for testing", "0.1.1", self.old_modules, self.old_packages) | ||||||
|  |         new_recipe = recipes.Recipe("test-recipe", "A recipe used for testing", "0.3.1", self.new_modules, self.new_packages) | ||||||
|  |         result = [{'new': {'Version': '0.3.1'}, 'old': {'Version': '0.1.1'}}, | ||||||
|  |                   {'new': {'Module': {'name': 'openssh', 'version': '2.8.1'}}, 'old': None}, | ||||||
|  |                   {'new': None, 'old': {'Module': {'name': 'bash', 'version': '4.*'}}}, | ||||||
|  |                   {'new': {'Module': {'name': 'httpd', 'version': '3.8.*'}}, | ||||||
|  |                    'old': {'Module': {'name': 'httpd', 'version': '3.7.*'}}}, | ||||||
|  |                   {'new': {'Package': {'name': 'git', 'version': '2.13.*'}}, 'old': None}] | ||||||
|  |         self.assertEqual(recipes.recipe_diff(old_recipe, new_recipe), result) | ||||||
| 
 | 
 | ||||||
| class GitRecipesTest(unittest.TestCase): | class GitRecipesTest(unittest.TestCase): | ||||||
|     @classmethod |     @classmethod | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user