django_evolution.utils.graph

Dependency graphs for tracking and ordering evolutions and migrations.

New in version 2.1.

Classes

DependencyGraph()

A graph tracking dependencies between nodes.

EvolutionGraph(*args, **kwargs)

A graph tracking dependencies between migrations and evolutions.

Node(key, insert_index, state)

A node in a graph.

Exceptions

NodeNotFoundError(key)

A requested node could not be found.

exception django_evolution.utils.graph.NodeNotFoundError(key)

Bases: Exception

A requested node could not be found.

New in version 2.1.

__init__(key)

Initialize the error.

Parameters:

key (unicode) – The key corresponding to the missing node.

class django_evolution.utils.graph.Node(key, insert_index, state)

Bases: object

A node in a graph.

Each node is associated with a key, and tracks caller-provided state, dependency relations (in both directions), and an insertion order (for loose sorting).

New in version 2.1.

dependencies

Any other nodes that this node depends on.

Type:

set of Node

insert_index

An index defining when this was added to the graph, relative to other nodes.

Type:

int

key

The key identifying this node.

Type:

unicode

required_by

Any other nodes that have this node as a dependency.

Type:

set of Node

state

Tracked state provided by the caller.

Type:

dict

__init__(key, insert_index, state)

Initialize the node.

Parameters:
  • key (unicode) – The key identifying this node.

  • insert_index (int) – An index defining when this was added to the graph, relative to other nodes.

  • state (dict) – Tracked state provided by the caller.

__hash__()

Return a hash of this node.

The hash will be based on the key.

Returns:

The hash for this node.

Return type:

int

__repr__()

Return a string representation of this node.

Returns:

The string representation.

Return type:

unicode

class django_evolution.utils.graph.DependencyGraph

Bases: object

A graph tracking dependencies between nodes.

This is used to model relations between objects, indicating which nodes require which, or are required by others, and then providing a sorted order based on those relations.

Dependencies can be added at any time, and are only applied once the graph is finalized. This allows nodes to be added after a dependency referring to them is added.

New in version 2.1.

__init__()

Initialize the graph.

add_node(key, state={})

Add a node to the graph.

A node can only be added if the graph has not been finalized and if the key has not already been recorded.

Parameters:
  • key (unicode) – The key uniquely identifying this node.

  • state (dict, optional) – State to add to the node.

Returns:

The resulting node.

Return type:

Node

add_dependency(node_key, dep_node_key)

Add a dependency between two nodes.

This will be recorded as a pending dependency and later applied to the nodes when calling finalize().

Parameters:
  • node_key (unicode) – The key of the node that depends on another node.

  • dep_node_key (unicode) – The key of the node that node_key depends on.

remove_dependencies(node_keys)

Remove any pending dependencies referencing one or more keys.

Parameters:

node_keys (set) – A set of node keys that should be removed from pending dependencies.

finalize()

Finalize the graph.

This will apply any dependencies and then mark the graph as finalized. At this point, orders can be computed, but no new nodes or dependencies can be added.

get_node(key)

Return a node with a corresponding key.

Parameters:

key (unicode) – The key associated with the node.

Returns:

The resulting node.

Return type:

Node

Raises:

NodeNotFoundError – The node could not be found.

get_leaf_nodes()

Return all leaf nodes on the graph.

Leaf nodes are nodes that nothing depends on. These are generally the last evolutions/migrations in any branch of the tree to apply.

Returns:

The list of leaf nodes, sorted by their insertion index.

Return type:

list of Node

get_ordered()

Return all nodes in dependency order.

This will perform a topological sort on the graph, returning nodes in the order they should be processed in.

The graph must be finalized before this is called.

Returns:

The list of ndoes, in dependency order.

Return type:

list of Node

class django_evolution.utils.graph.EvolutionGraph(*args, **kwargs)

Bases: DependencyGraph

A graph tracking dependencies between migrations and evolutions.

This is used to model the relationships between all configured migrations and evolutions, and to generate batches of consecutive migrations or evolutions that can be applied at once.

Dependencies can be added at any time, and are only applied once the graph is finalized. This allows nodes to be added after a dependency referring to them is added.

New in version 2.1.

NODE_TYPE_ANCHOR = 'anchor'

An anchor node.

These are internal, and are used for clustered dependency management.

NODE_TYPE_CREATE_MODEL = 'create-model'

A node that results in model creation.

NODE_TYPE_EVOLUTION = 'evolution'

A node that results in applying a single evolution.

NODE_TYPE_MIGRATION = 'migration'

A node that results in applying a single migration.

__init__(*args, **kwargs)

Initialize the graph.

Parameters:
  • *args (tuple) – Positional arguments for the parent.

  • **kwargs (dict) – Keyword arguments for the parent.

add_evolutions(app, evolutions=[], new_models=[], extra_state={}, custom_evolutions=[])

Add a list of evolutions for a given app.

Each evolution will gets its own node, and pending dependencies will be recorded to ensure the evolutions are applied in the correct order.

A special __first__ anchor node will be added before the sequence of evolutions, and a __last__ node will be added after. This allows evolutions to easily reference another app’s list of evolutions relative to the start or end of a list. It’s used only internally.

Changed in version 2.2: A custom_evolutions argument can now be provided, for dependency resolution purposes.

Parameters:
  • app (module) – The app module the evolutions apply to.

  • evolutions (list of django_evolution.models.Evolution, optional) – The list of evolutions to add to the graph. This may be an empty list if there are no evolutions but there are new models to create.

  • new_models (list of type, optional) – The list of database model classes to create for the app.

  • extra_state (dict, optional) – Extra state to set in each evolution node.

  • custom_evolutions (list of dict, optional) –

    An optional list of custom evolutions for the app, for dependency resolution.

    New in version 2.2.

add_migration_plan(migration_plan, migration_graph)

Add a migration plan to the graph.

Each migration in the plan will gets its own node, and pending dependencies will be recorded to ensure the migrations are applied in the order already computed for the plan.

Parameters:
  • migration_plan (list of tuple) – The computed migration plan to add to the graph.

  • migration_graph (django.db.migrations.graph.MigrationGraph) – The computed migration graph, used to reference computed dependencies.

mark_evolutions_applied(app, evolution_labels)

Mark one or more evolutions as applied.

This will remove any pending dependencies referencing these evolutions from the graph.

Parameters:
  • app (module) – The app module the evolutions apply to.

  • evolution_labels (list of unicode) – The list of evolutions labels to mark as applied.

mark_migrations_applied(migrations)

Mark one or more migrations as applied.

This will remove any pending dependencies referencing these migrations from the graph.

Parameters:

migrations (django_evolution.utils.migrations.MigrationList) – The list of migrations to mark as applied.

iter_batches()

Iterate through batches of consecutive evolutions and migrations.

The nodes will be iterated in dependency order, with each batch containing a sequence of either evolutions or migrations that can be applied at once.

Yields:

tuple – A 2-tuple containing:

  1. The batch type (one of NODE_TYPE_CREATE_MODEL, NODE_TYPE_EVOLUTION, or NODE_TYPE_MIGRATION).

  2. A list of Node instances.