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)
Example #3
0
    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)