========================================== Changing Resource Structure With Evolution ========================================== As you develop your software and make changes to structures, your existing content will be in an old state. Whether in production or during development, you need a facility to correct out-of-date data. Evolution provides a rich facility for "evolving" your resources to match changes during development. Substance D's evolution facility gives Substance D developers full control over the data updating process: - Write scripts for each package that get called during an update - Set revision markers in the data to indicate the revision level a database is at - Console script and SDI GUI that can be run to "evolve" a database .. _sd_evolve-narrative: Running an Evolution from the Command Line ========================================== Substance D applications generate a console script at ``bin/sdi_evolve``. Running this without arguments displays some help: .. code-block:: bash $ bin/sd_evolve Requires a config_uri as an argument sd_evolve [--latest] [--dry-run] [--mark-finished=stepname] [--mark-unfinished=stepname] config_uri Evolves new database with changes from scripts in evolve packages - with no arguments, evolve displays finished and unfinished steps - with the --latest argument, evolve runs scripts as necessary - with the --dry-run argument, evolve runs scripts but does not issue any commits - with the --mark-finished argument, marks the stepname as finished - with the --mark-unfinished argument, marks the stepname as unfinished e.g. sd_evolve --latest etc/development.ini Running with your INI file, as explained in the help, shows information about the version numbers of various packages: .. code-block:: bash $ bin/sd_evolve etc/development.ini Finished steps: 2013-06-14 13:01:28 substanced.evolution.legacy_to_new Unfinished steps: This shows that one evolution step has already been run and that there are no unfinished evolution steps. Running an Evolution from the SDI ================================= The Evolution section of the ``Database`` tab of the Substance D root object allows you to do what you might have otherwise done using the ``sd_evolve`` console script described above. In some circumstances when Substance D itself needs to be upgraded, you may need to use the ``sd_evolve`` script rather than the GUI. For example, if the way that Substance D ``Folder`` objects work is changed and folder objects need to be evolved, it may be impossible to view the evolution GUI, and you may need to use the console script. Autoevolve ========== If you add ``substanced.autoevolve = true`` within your application .ini file, all pending evolution upgrade steps will be run when your application starts. Alternately you can use the ``SUBSTANCED_AUTOEVOLVE`` evnironment variable (e.g. ``export SUBSTANCED_AUTOEVOLVE=true``) to do the same thing. Adding Evolution Support To a Package ===================================== Let's say we have been developing an ``sdidemo`` package and, with content already in the database, we want to add evolution support. Our ``sdidemo`` package is designed to be included into a site, so we have the traditional Pyramid ``includeme`` support. In there we add the following: .. code-block:: python import logging logger = logging.getLogger('evolution') def evolve_stuff(root, registry): logger.info('Stuff evolved.') def includeme(config): config.add_evolution_step(evolve_stuff) We've used the :func:`substanced.evolution.add_evolution_step` API to add an evolution step in this package's ``includeme`` function. Running ``sd_evolve`` *without* ``--latest`` (meaning, without performing an evolution) shows that Substance D's evolution now knows about our package: .. code-block:: bash $ bin/sd_evolve etc/development.ini Finished steps: 2013-06-14 13:01:28 substanced.evolution.legacy_to_new Unfinished steps: sdidemo.evolve_stuff Let's now run ``sd_evolve`` "for real". This will cause the evolution step to be executed and marked as finished. .. code-block:: bash $ bin/sd_evolve --latest etc/development.ini 2013-06-14 13:22:51,475 INFO [evolution][MainThread] Stuff evolved. Evolution steps executed: substanced.evolution.evolve_stuff This examples shows a number of points: - Each package can easily add evolution support via the ``config.add_evolution_step()`` directive. You can learn more about this directive by reading its API documentation at :func:`substanced.evolution.add_evolution_step`. - Substance D's evolution service looks at the database to see which steps haven't been run, then runs all the needed evolve scripts, sequentially, to bring the database up to date. - All changes within an evolve script are in the scope of a transaction. If all the evolve scripts run to completion without exception, the transaction is committed. Manually Marking a Step As Evolved ================================== In some cases you might have performed the work in an evolve step by hand and you know there is no need to re-perform that work. You'd like to mark the step as finished for one or more evolve scripts, so these steps don't get run. The ``--mark-step-finished`` argument to ``sd_evolve`` accomplishes this. The "Mark finished" button in the SDI evolution GUI does the same. Baselining ========== Evolution is baselined at first startup. When there's no initial list of finished steps in the database. Substance D, in the root factory, says: "I know all the steps participating in evolution, so when I first create the root object, I will set all of those steps to finished." If you wish to perform something after :class:`~substanced.root.Root` was created, see :ref:`affecting_content_creation`.