API — Recipe 0.2.2 documentation

# API

This part of the documentation covers all the interfaces of Recipe.

## Recipe

class `recipe.` `Recipe`(shelf=None, metrics=None, dimensions=None, filters=None, order_by=None, select_from=None, session=None, extension_classes=None, dynamic_extensions=None)

  A tool for getting data.

  Parameters: | shelf (Shelf) – A shelf to use for shared metrics metrics (`list` of `str`) – A list of metrics to use from the shelf. These can also be `Metric` objects. dimensions (`list` of `str`) – A list of dimensions to use from the shelf. These can also be `Dimension` objects. filters (`list` of `str`) – A list of filters to use from the shelf. These can also be `Filter` objects. order_by (`list` of `str`) – A list of dimension or metric keys from the shelf to use for ordering. If prefixed by ‘-‘ the ordering will be descending. session (`Session`) extension_classes (`list` of `RecipeExtension`) – Extensions to apply to this recipe.
  Returns: | A Recipe object.

  `all`()

    Return a (potentially cached) list of result objects.

  `as_table`(name=None)

    Return an alias to a table

  `dimensions`(*dimensions)

    Add a list of Dimension ingredients to the query. These can either be Dimension objects or strings representing dimensions on the shelf.

    The Dimension expression will be added to the query’s select statement and to the group_by.

    Parameters: | dimensions (list) – Dimensions to add to the recipe. Dimensions can either be keys on the `shelf` or Dimension objects

  `dirty`

    The recipe is dirty if it is flagged dirty or any extensions are flagged dirty

  `filters`(*filters)

    Add a list of Filter ingredients to the query. These can either be Filter objects or strings representing filters on the service’s shelf. `.filters()` are additive, calling .filters() more than once will add to the list of filters being used by the recipe.

    The Filter expression will be added to the query’s where clause

    Parameters: | filters (list) – Filters to add to the recipe. Filters can either be keys on the `shelf` or Filter objects

  `first`()

    Return the first element on the result

  `limit`(limit)

    Limit the number of rows returned from the database.

    Parameters: | limit (int) – The number of rows to return in the recipe. 0 will return all rows.

  `metrics`(*metrics)

    Add a list of Metric ingredients to the query. These can either be Metric objects or strings representing metrics on the shelf.

    The Metric expression will be added to the query’s select statement. The metric value is a property of each row of the result.

    Parameters: | metrics (list) – Metrics to add to the recipe. Metrics can either be keys on the `shelf` or Metric objects

  `offset`(offset)

    Offset a number of rows before returning rows from the database.

    Parameters: | offset (int) – The number of rows to offset in the recipe. 0 will return from the first available row

  `one`()

    Return the first element on the result

  `order_by`(*order_bys)

    Add a list of ingredients to order by to the query. These can either be Dimension or Metric objects or strings representing order_bys on the shelf.

    The Order_by expression will be added to the query’s order_by statement

    Parameters: | order_bys (list) – Order_bys to add to the recipe. Order_bys can either be keys on the `shelf` or Dimension or Metric objects. If the key is prefixed by “-” the ordering will be descending.

  `query`()

    Generates a query using the ingredients supplied by the recipe.

    Returns: | A SQLAlchemy query

  `shelf`(shelf=None)

    Defines a shelf to use for this recipe

  `subquery`(name=None)

    The recipe’s query as a subquery suitable for use in joins or other queries.

  `to_sql`()

    A string representation of the SQL this recipe will generate.

## Shelf

class `recipe.` `Shelf`(*args, **kwargs)

  Holds ingredients used by a recipe

  Args:

  Returns: | A Shelf object

  `brew_query_parts`()

    Make columns, group_bys, filters, havings

  `clear`() → None. Remove all items from D.
  `copy`() → a shallow copy of D
  `dimension_ids`

    Return the Dimensions on this shelf in the order in which they were used.

  `enchant`(list, cache_context=None)

    Add any calculated values to each row of a resultset generating a new namedtuple

    Parameters: | list – a list of row results cache_context – optional extra context for caching
    Returns: | a list with ingredient.cauldron_extras added for all ingredients

  `filter_ids`

    Return the Filters on this shelf in the order in which they were used.

  `find`(obj, filter_to_class=<class 'recipe.ingredients.Ingredient'>, constructor=None)

    Find an Ingredient, optionally using the shelf.

    Parameters: | obj – A string or Ingredient filter_to_class – The Ingredient subclass that obj must be an instance of constructor – An optional callable for building Ingredients from obj
    Returns: | An Ingredient of subclass filter_to_class

  `fromkeys`(S[, v]) → New dict with keys from S and values equal to v.

    v defaults to None.

  `has_key`(k) → True if D has a key k, else False
  `ingredients`()

    Return the ingredients in this shelf in a deterministic order

  `items`() → list of D's (key, value) pairs, as 2-tuples
  `iteritems`() → an iterator over the (key, value) items of D
  `iterkeys`() → an iterator over the keys of D
  `itervalues`() → an iterator over the values of D
  `keys`() → list of D's keys
  `metric_ids`

    Return the Metrics on this shelf in the order in which they were used.

  `pop`(k[, d]) → v, remove specified key and return the corresponding value.

    If key is not found, d is returned if given, otherwise KeyError is raised

  `popitem`() → (k, v), remove and return some (key, value) pair as a

    2-tuple; but raise KeyError if D is empty.

  `setdefault`(k[, d]) → D.get(k,d), also set D[k]=d if k not in D
  `update`([E, ]**F) → None. Update D from dict/iterable E and F.

    If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]

  `values`() → list of D's values
  `viewitems`() → a set-like object providing a view on D's items
  `viewkeys`() → a set-like object providing a view on D's keys
  `viewvalues`() → an object providing a view on D's values

class `recipe.` `AutomaticShelf`(table, *args, **kwargs)
  `brew_query_parts`()

    Make columns, group_bys, filters, havings

  `clear`() → None. Remove all items from D.
  `copy`() → a shallow copy of D
  `dimension_ids`

    Return the Dimensions on this shelf in the order in which they were used.

  `enchant`(list, cache_context=None)

    Add any calculated values to each row of a resultset generating a new namedtuple

    Parameters: | list – a list of row results cache_context – optional extra context for caching
    Returns: | a list with ingredient.cauldron_extras added for all ingredients

  `filter_ids`

    Return the Filters on this shelf in the order in which they were used.

  `find`(obj, filter_to_class=<class 'recipe.ingredients.Ingredient'>, constructor=None)

    Find an Ingredient, optionally using the shelf.

    Parameters: | obj – A string or Ingredient filter_to_class – The Ingredient subclass that obj must be an instance of constructor – An optional callable for building Ingredients from obj
    Returns: | An Ingredient of subclass filter_to_class

  `fromkeys`(S[, v]) → New dict with keys from S and values equal to v.

    v defaults to None.

  `has_key`(k) → True if D has a key k, else False
  `ingredients`()

    Return the ingredients in this shelf in a deterministic order

  `items`() → list of D's (key, value) pairs, as 2-tuples
  `iteritems`() → an iterator over the (key, value) items of D
  `iterkeys`() → an iterator over the keys of D
  `itervalues`() → an iterator over the values of D
  `keys`() → list of D's keys
  `metric_ids`

    Return the Metrics on this shelf in the order in which they were used.

  `pop`(k[, d]) → v, remove specified key and return the corresponding value.

    If key is not found, d is returned if given, otherwise KeyError is raised

  `popitem`() → (k, v), remove and return some (key, value) pair as a

    2-tuple; but raise KeyError if D is empty.

  `setdefault`(k[, d]) → D.get(k,d), also set D[k]=d if k not in D
  `update`([E, ]**F) → None. Update D from dict/iterable E and F.

    If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]

  `values`() → list of D's values
  `viewitems`() → a set-like object providing a view on D's items
  `viewkeys`() → a set-like object providing a view on D's keys
  `viewvalues`() → an object providing a view on D's values

## Ingredients

class `recipe.` `Ingredient`(**kwargs)

  Ingredients combine to make a SQLAlchemy query.

  `build_filter`(value, operator=None)

    Builds a filter based on a supplied value and optional operator. If no operator is supplied an `in` filter will be used for a list and a `eq` filter if we get a scalar value

    Parameters: | value (object) – The value to use in the filter operator (str) – An operator to override the default interaction

  `cauldron_extras`

    Yield extra tuples containing a field name and a callable that takes a row

  `expression`

    An accessor for the sqlalchemy expression representing this Ingredient

  `make_column_suffixes`()

    Make sure we have the right column suffixes. These will be appended to id when generating the query.

  `query_columns`

    Yield labeled columns to be used as a select in a query

class `recipe.` `Dimension`(expression, **kwargs)

  A simple dimension created from a single expression and optional id_expression

  `cauldron_extras`

    Yield extra tuples containing a field name and a callable that takes a row

  `id_prop`

    The label of this dimensions id in the query columns

  `make_column_suffixes`()

    Make sure we have the right column suffixes. These will be appended to id when generating the query.

class `recipe.` `IdValueDimension`(id_expression, value_expression, **kwargs)

class `recipe.` `Metric`(expression, **kwargs)

  A simple metric created from a single expression

class `recipe.` `DivideMetric`(numerator, denominator, **kwargs)

  A metric that divides a numerator by a denominator handling several possible error conditions

  The default strategy is to add an small value to the denominator Passing ifzero allows you to give a different value if the denominator is zero.

class `recipe.` `Filter`(expression, **kwargs)

  A simple filter created from a single expression.

  `expression`

    An accessor for the sqlalchemy expression representing this Ingredient

class `recipe.` `Having`(expression, **kwargs)

  A Having that limits results based on an aggregate boolean clause

  `expression`

    An accessor for the sqlalchemy expression representing this Ingredient

## Extensions

class `recipe.` `RecipeExtension`(recipe)

  Recipe extensions plug into the recipe builder pattern and can modify the generated query.

  The extension should mark itself as `dirty` if it has changes which change the current recipe results.

  recipe generates a query in the following way

  > (RECIPE) recipe checks its dirty state and all extension dirty states to determine if the cached query needs to be regenerated

  > (EXTENSIONS) all extension `add_ingredients` run to inject ingredients directly on the recipe

  > (RECIPE) recipe runs gather_all_ingredients_into_cauldron to build a global lookup for ingredients

  > (RECIPE) recipe runs cauldron.brew_query_parts to gather sqlalchemy columns, group_bys and filters

  > (EXTENSIONS) all extension `modify_recipe_parts(recipeparts)` run to directly modify the collected sqlalchemy columns, group_bys or filters

  > (RECIPE) recipe builds a preliminary query with columns

  > (EXTENSIONS) all extension `modify_prequery_parts(prequery_parts)` run to modify the query

  > (RECIPE) recipe builds a full query with group_bys, order_bys, and filters.

  > (RECIPE) recipe tests that this query only uses a single from

  > (EXTENSIONS) all extension `modify_postquery_parts( postquery_parts)` run to modify the query

  > (RECIPE) recipe applies limits and offsets on the query

  > (RECIPE) recipe caches completed query and sets all dirty flags to False.

  When the recipe fetches data the results will be `enchanted` to add fields to the result. `RecipeExtensions` can modify result rows with

  > enchant_add_fields: Return a tuple of field names to add to a result row

  > enchant_row(row): Return a tuple of field values for each row in results.

  `add_ingredients`()

    Add ingredients to the recipe

    This method should be overridden by subclasses

  `enchant_add_fields`()

    This method allows extensions to add fields to a result row. Return a tuple of the field names that are being added with this method

  `enchant_row`(row)

    This method adds the fields named in `enchant_add_fields` to each result row.

  `modify_postquery_parts`(postquery_parts)

    This method allows extensions to directly modify query, group_bys, filters, and order_bys generated from collected ingredients after a final query using columns has been created.

  `modify_prequery_parts`(prequery_parts)

    This method allows extensions to directly modify query, group_bys, filters, and order_bys generated from collected ingredients after a preliminary query using columns has been created.

  `modify_recipe_parts`(recipe_parts)

    Modify sqlalchemy components of the query

    This method allows extensions to directly modify columns, group_bys, filters, and order_bys generated from collected ingredients.

class `recipe.` `AutomaticFilters`(*args, **kwargs)

  Automatic generation and addition of Filters to a recipe.

  Automatic filters take a dictionary of keys and values. For each key in the dictionary, if the key is the id of a `Dimension` on the shelf, a filter will be added to the recipe containing the values.

  `apply_automatic_filters`(value)

    Toggles whether automatic filters are applied to a recipe. The following will disable automatic filters for this recipe:

        recipe.apply_automatic_filters(False)

  `automatic_filters`(value)

    Sets a dictionary of automatic filters to apply to this recipe. If your recipe uses a shelf that has dimensions ‘state’ and ‘gender’ you could filter the data to Men in California and New Hampshire with:

        shelf = Shelf({
            'state': Dimension(Census.state),
            'gender': Dimension(Census.gender),
            'population': Metric(func.sum(Census.population)),
        })
        recipe = Recipe(shelf=shelf)
        recipe.dimensions('state').metrics('population').automatic_filters({
            'state': ['California', 'New Hampshire'],
            'gender': 'M'
        })

    Automatic filter keys can optionally include an `operator`.

    List operators

    If the value provided in the automatic_filter dictionary is a list, the following operators are available. The default operator is `in`:

        in (default)
        notin
        between (requires a list of two items)

    Scalar operators

    If the value provided in the automatic_filter dictionary is a scalar (a string, integer, or number), the following operators are available. The default operator is `eq`:

        eq (equal) (the default)
        ne (not equal)
        lt (less than)
        lte (less than or equal)
        gt (greater than)
        gte (greater than or equal)

    An example using operators

    Here’s an example that filters to states that start with the letters A-C:

        shelf = Shelf({
            'state': Dimension(Census.state),
            'gender': Dimension(Census.gender),
            'population': Metric(func.sum(Census.population)),
        })
        recipe = Recipe(shelf=shelf)
        recipe.dimensions('state').metrics('population').automatic_filters({
            'state__lt': 'D'
        })

  `exclude_automatic_filter_keys`(*keys)

    A “blacklist” of automatic filter keys to exclude. The following will cause `'state'` to be ignored if it is present in the `automatic_filters` dictionary.:

        recipe.exclude_automatic_filter_keys('state')

  `include_automatic_filter_keys`(*keys)

    A “whitelist” of automatic filter keys to use. The following will only use `'state'` for automatic filters regardless of what is provided in the automatic_filters dictionary.:

        recipe.include_automatic_filter_keys('state')

class `recipe.` `BlendRecipe`(*args, **kwargs)

  Add blend recipes, used for joining data from another table to a base table

  Supply a second recipe with a different `from` Optionally supply join criteria, if no join criteria is provided join will be attempted using constraints. All ingredients from the blended recipe will be hoisted to the base recipe except for ingredients that are used for joins (they must be the same anyway).

  Supports blend (inner) and full_blend (outer) joins.

  `blend`(blend_recipe, join_base, join_blend)

    Blend a recipe into the base recipe. This performs an inner join of the blend_recipe to the base recipe’s SQL.

  `full_blend`(blend_recipe, join_base, join_blend)

    Blend a recipe into the base recipe preserving values from both recipes.

    This performs an outer join of the blend_recipe to the base recipe.

class `recipe.` `CompareRecipe`(*args, **kwargs)

  Add compare recipes, used for presenting comparative context vis-a-vis a base recipe.

  Supply a second recipe with the same ``from`. Metrics from the second recipe will be hoisted to the base recipe and suffixed with a string (the default is “_compare” Dimensions will be used to match the base recipe to the compare recipe. Ordering from the base recipe is maintained.

  `compare`(compare_recipe, suffix='_compare')

    Adds a comparison recipe to a base recipe.

class `recipe.` `Anonymize`(*args, **kwargs)

  Allows recipes to be anonymized by adding an anonymize property This flips the anonymize flag on all Ingredients used in the recipe.

  Injects an ingredient.meta._anonymize boolean property on each used ingredient.

  AnonymizeRecipe should occur last

  `add_ingredients`()

    Put the anonymizers in the last position of formatters

  `anonymize`(value)

    Should this recipe be anonymized

## Exceptions

exception `recipe.` `BadIngredient`

  Something is wrong with an ingredient

exception `recipe.` `BadRecipe`

  Something is wrong with a recipe

Now, go start some Recipe Development.