def _add_from_recipe_parts(self, recipe_parts): """ Adds a recipe, but doesn't commit the transaction. """ # First, make sure that we're not inserting a duplicate record. # Duplicates are considered to be recipes with the same url. duplicate = self._session.query(Recipe).\ filter_by(url=recipe_parts['url']) if duplicate.first(): raise DuplicateRecipeException( "Recipe with url %s already exists." % recipe_parts['url']) recipe = Recipe() recipe_parts = defaultdict(str, recipe_parts) recipe.title = recipe_parts['title'] recipe.url = recipe_parts['url'] recipe.author = recipe_parts['author'] recipe.description = recipe_parts['description'] recipe.num_steps = recipe_parts['num_steps'] recipe.servings = recipe_parts['servings'] recipe.prep_time = recipe_parts['prep_time'] recipe.cook_time = recipe_parts['cook_time'] recipe.total_time = recipe_parts['total_time'] recipe.ingredients_text = "\n".join(recipe_parts['ingredients']) recipe.steps_text = "\n".join(recipe_parts['steps']) for ingredient_string in recipe_parts['ingredients']: ingredient_parts = extract_ingredient_parts(ingredient_string) if not ingredient_parts: continue ingredient_parts = defaultdict(lambda: None, ingredient_parts) ingredient = self.get_ingredients( name=ingredient_parts['base_ingredient']).first() if not ingredient: ingredient = self._new_ingredient(ingredient_parts['base_ingredient']) self._session.add(ingredient) unit = ingredient_parts['unit'] quantity = ingredient_parts['quantity'] modifiers = ingredient_parts['modifiers'] assoc = RecipeIngredientAssociation(ingredient, unit, quantity, modifiers) recipe.ingredients.append(assoc) # The ingredient count is stored as a part of the reicpe to avoid # expensive subqueries when filtering recipes based on the number of # ingredients that they contain. It's unlikely that recipes would be # modified after they're imported, but there should probably be # a trigger to ensure that this count remains up to date. # The count is set after processing the ingredient string to prevent # headings like "CRUST: " from contributing to the ingredient count. recipe.num_ingredients = len(recipe.ingredients) # Add cuisines for cuisine_name in recipe._determine_cuisines(): cuisine = self.get_cuisines(name=cuisine_name).first() if not cuisine: cuisine = Cuisine(cuisine_name) self._session.add(cuisine) recipe.cuisines.append(cuisine) self._session.add(recipe)
def main(): """ Run the accuracy tests. """ skipped = 0 passed = 0 failed = 0 testdata = csv.reader(urllib2.urlopen(TESTDATA_URL)) testdata.next() # Skip header for case in testdata: if len(case) < 4: skipped += 1 continue # Skip incomplete testcases expected = { 'quantity': case[1], 'unit': case[2], 'modifiers': case[3], 'base_ingredient': case[4], } for key in expected.keys(): if not expected[key]: del expected[key] actual = extract_ingredient_parts(case[0]) if actual != expected: print "Expected: %s" % str(expected) print " Actual: %s" % str(actual) print failed += 1 else: passed += 1 print "Skipped: %i" % skipped print " Passed: %i" % passed print " Failed: %i" % failed print " Total: %i" % (failed + skipped + passed)
def _add_from_recipe_parts(self, recipe_parts): """ Adds a recipe, but doesn't commit the transaction. """ # First, make sure that we're not inserting a duplicate record. # Duplicates are considered to be recipes with the same url. duplicate = self._session.query(Recipe).\ filter_by(url=recipe_parts['url']) if duplicate.first(): raise DuplicateRecipeException( "Recipe with url %s already exists." % recipe_parts['url']) recipe = Recipe() recipe_parts = defaultdict(str, recipe_parts) recipe.title = recipe_parts['title'] recipe.url = recipe_parts['url'] recipe.author = recipe_parts['author'] recipe.description = recipe_parts['description'] recipe.num_steps = recipe_parts['num_steps'] recipe.servings = recipe_parts['servings'] recipe.prep_time = recipe_parts['prep_time'] recipe.cook_time = recipe_parts['cook_time'] recipe.total_time = recipe_parts['total_time'] recipe.ingredients_text = "\n".join(recipe_parts['ingredients']) recipe.steps_text = "\n".join(recipe_parts['steps']) for ingredient_string in recipe_parts['ingredients']: ingredient_parts = extract_ingredient_parts(ingredient_string) if not ingredient_parts: continue ingredient_parts = defaultdict(lambda: None, ingredient_parts) ingredient = self.get_ingredients( name=ingredient_parts['base_ingredient']).first() if not ingredient: ingredient = self._new_ingredient( ingredient_parts['base_ingredient']) self._session.add(ingredient) unit = ingredient_parts['unit'] quantity = ingredient_parts['quantity'] modifiers = ingredient_parts['modifiers'] assoc = RecipeIngredientAssociation(ingredient, unit, quantity, modifiers) recipe.ingredients.append(assoc) # The ingredient count is stored as a part of the reicpe to avoid # expensive subqueries when filtering recipes based on the number of # ingredients that they contain. It's unlikely that recipes would be # modified after they're imported, but there should probably be # a trigger to ensure that this count remains up to date. # The count is set after processing the ingredient string to prevent # headings like "CRUST: " from contributing to the ingredient count. recipe.num_ingredients = len(recipe.ingredients) # Add cuisines for cuisine_name in recipe._determine_cuisines(): cuisine = self.get_cuisines(name=cuisine_name).first() if not cuisine: cuisine = Cuisine(cuisine_name) self._session.add(cuisine) recipe.cuisines.append(cuisine) self._session.add(recipe)