======================
Changes in version 0.9
======================

This document details the various backwards-incompatible changes made during
Fabric's rewrite between versions 0.1 and 0.9. The codebase has been almost
completely rewritten and reorganized and an attempt has been made to remove
"magical" behavior and make things more simple and Pythonic; the ``fab``
command-line component has also been redone to behave more like a typical Unix
program.


Major changes
=============

You'll want to at least skim the entire document, but the primary changes that
will need to be made to one's fabfiles are as follows:

Imports
-------

You will need to **explicitly import any and all methods or decorators used**,
at the top of your fabfile; they are no longer magically available. Here's a
sample fabfile that worked with 0.1 and earlier::

     @hosts('a', 'b')
     def my_task():
         run('ls /var/www')
         sudo('mkdir /var/www/newsite')

The above fabfile uses `hosts`, `run` and `sudo`, and so in Fabric 0.9 one
simply needs to import those objects from the new API module ``fabric.api``::

     from fabric.api import hosts, run, sudo

     @hosts('a', 'b')
     def my_task():
         run('ls /var/www')
         sudo('mkdir /var/www/newsite')

You may, if you wish, use ``from fabric.api import *``, though this is
technically not Python best practices; or you may import directly from the
Fabric submodules (e.g. ``from fabric.decorators import hosts``.)
See :doc:`../usage/fabfiles` for more information.

Python version
--------------

Fabric started out Python 2.5-only, but became largely 2.4 compatible at one
point during its lifetime. Fabric is once again **only compatible with Python
2.5 or newer**, in order to take advantage of the various new features and
functions available in that version.

With this change we're setting an official policy to support the two most
recent stable releases of the Python 2.x line, which at time of writing is 2.5
and 2.6. We feel this is a decent compromise between new features and the
reality of operating system packaging concerns. Given that most users use
Fabric from their workstations, which are typically more up-to-date than
servers, we're hoping this doesn't cut out too many folks.

Finally, note that while we will not officially support a 2.4-compatible
version or fork, we may provide a link to such a project if one arises.

Environment/config variables
----------------------------

The ``config`` object previously used to access and set internal state
(including Fabric config options) **has been renamed** to :data:`env`, but
otherwise remains mostly the same (it allows both dictionary and
object-attribute style access to its data.) :data:`env` resides in the
:mod:`state` submodule and is importable via ``fabric.api``, so where before
one might have seen fabfiles like this::

    def my_task():
        config.foo = 'bar'

one will now be explicitly importing the object like so::

    from fabric.api import env

    def my_task():
        env.foo = 'bar'

Execution mode
--------------

Fabric's default mode of use, in prior versions, was what we called "broad
mode": your tasks, as Python code, ran only once, and any calls to functions
that made connections (such as `run` or `sudo`) would run once per host in the
current host list. We also offered "deep mode", in which your entire task
function would run once per host.

In Fabric 0.9, this dichotomy has been removed, and **"deep mode" is the
method Fabric uses to perform all operations**. This allows you to treat your
Fabfiles much more like regular Python code, including the use of ``if``
statements and so forth, and allows operations like `run` to unambiguously
return the output from the server.

Other modes of execution such as the old "broad mode" may return as Fabric's
internals are refactored and expanded, but for now we've simplified things, and
deep mode made the most sense as the primary mode of use.

"Lazy" string interpolation
---------------------------

Because of how Fabric used to run in "broad mode" (see previous section) a
special string formatting technique -- the use of a bash-like dollar sign
notation, e.g. ``"hostname: $(fab_host)"`` -- had to be used to allow the
current state of execution to be represented in one's operations. **This is no
longer necessary and has been removed**. Because your tasks are executed once
per host, you may build strings normally (e.g. with the ``%`` operator) and
refer to ``env.host_string``, ``env.user`` and so forth.

For example, Fabric 0.1 had to insert the current username like so::

    print("Your current username is $(fab_user)")

Fabric 0.9 and up simply reference ``env`` variables as normal::

    print("Your current username is %s" % env.user)

As with the execution modes, a special string interpolation function or method
that automatically makes use of ``env`` values may find its way back into
Fabric at some point if a need becomes apparent.


Other backwards-incompatible changes
====================================

In no particular order:

* The Fabric config file location used to be ``~/.fabric``; in the interests
  of honoring Unix filename conventions, it's now ``~/.fabricrc``.

* The old ``config`` object (now :data:`env`) had a ``getAny`` method which
  took one or more key strings as arguments, and returned the value attached
  to the first valid key. This method still exists but has been renamed to
  `first`.

* Environment variables such as ``fab_host`` have been renamed to simply e.g.
  ``host``. This looks cleaner and feels more natural, and requires less
  typing. Users will naturally need to be careful not to override these
  variables, but the same holds true for e.g. Python's builtin methods and
  types already, so we felt it was worth the tradeoff.

* Fabric's version header is no longer printed every time the program runs;
  you should now use the standard ``--version``/``-V`` command-line options to
  print version and exit.

* The old ``about`` command has been removed; other Unix programs don't
  typically offer this. Users can always view the license and warranty info in
  their respective text files distributed with the software.

* The old ``help`` command is now the typical Unix options ``-h``/``--help``.

    * Furthermore, there is no longer a listing of Fabric's programming API
      available through the command line -- those topics impact fabfile
      authors, not fab users (even though the former is a subset of the
      latter) and should stay in the documentation only.

* `prompt`'s primary function is now to return a value to the caller, although
  it may still optionally store the entered value in `env` as well.

* `prompt` now considers the empty string to be valid input; this allows other
  functions to wrap `prompt` and handle "empty" input on their own terms.

* In addition to the above changes, `prompt` has been updated to behave more
  obviously, as its previous behavior was confusing in a few ways:

    * It will now overwrite pre-existing values in the environment dict, but
      will print a warning to the user if it does so.

    * Additionally, (and this appeared to be undocumented) the ``default``
      argument could take a callable as well as a string, and would simply set
      the default message to the return value if a callable was given. This
      seemed to add unnecessary complexity (given that users may call e.g.
      ``prompt(blah, msg, default=my_callable()``) so it has been removed.

* When connecting, Fabric used to use the undocumented ``fab_pkey`` env
  variable as a method of passing in a Paramiko ``PKey`` object to the SSH
  client's ``connect`` method. This has been removed in favor of an
  ``ssh``-like ``-i`` option, which allows one to specify a private key file
  to use; that should generally be enough for most users.

* ``download`` is now `get` in order to match up with `put` (the name mismatch
  was due to `get` being the old method of getting env vars.)

* The ``noshell`` argument to `sudo` (added late in its life to previous
  Fabric versions) has been renamed to ``shell`` (defaults to True, so the
  effective behavior remains the same) and has also been extended to the `run`
  operation.

    * Additionally, the global ``sudo_noshell`` option has been renamed to
      ``use_shell`` and also applies to both `run` and `sudo`.

* ``local_per_host`` has been removed, as it only applied to the now-removed
  "broad mode".

* ``load`` has been removed; Fabric is now "just Python", so use Python's
  import mechanisms in order to stitch multiple fabfiles together.

* ``abort`` is no longer an "operation" *per se* and has been moved to
  :mod:`fabric.utils`. It is otherwise the same as before, taking a single
  string message, printing it to the user and then calling ``sys.exit(1)``.

* ``rsyncproject`` and ``upload_project`` have been moved into
  :mod:`fabric.contrib` (specifically, :mod:`fabric.contrib.project`), which
  is intended to be a new tree of submodules for housing "extra" code which
  may build on top of the core Fabric operations.

* ``invoke`` has been turned on its head, and is now the `runs_once` decorator
  (living in :mod:`fabric.decorators`). When used to decorate a function, that
  function will only execute one time during the lifetime of a ``fab`` run.
  Thus, where you might have used ``invoke`` multiple times to ensure a given
  command only runs once, you may now use `runs_once` to decorate the function
  and then call it multiple times in a normal fashion.

* It looks like the regex behavior of the ``validate`` argument to `prompt`
  was never actually implemented. It now works as advertised.

* Couldn't think of a good reason for `require` to be a decorator *and* a
  function, and the function is more versatile in terms of where it may be
  used, so the decorator has been removed.

* As things currently stand with the execution model, the ``depends``
  decorator doesn't make a lot of sense: instead, it's safest/best to simply
  make "meta" commands that just call whatever chain of "real" commands you
  need performed for a given overarching task.

  For example, instead of having command A say
  that it "depends on" command B, create a command C which calls A and B in the
  right order, e.g.::

    def build():
        local('make clean all')

    def upload():
        put('app.tgz', '/tmp/app.tgz')
        run('tar xzf /tmp/app.tgz')

    def symlink():
        run('ln -s /srv/media/photos /var/www/app/photos')

    def deploy():
        build()
        upload()
        symlink()

  .. note::

    The execution model is still subject to change as Fabric evolves. Please
    don't hesitate to email the list or the developers if you have a use case
    that needs something Fabric doesn't provide right now!

* Removed the old ``fab shell`` functionality, since the move to "just Python"
  should make vanilla ``python``/``ipython`` usage of Fabric much easier.

    * We may add it back in later as a convenient shortcut to what basically
      amounts to running ``ipython`` and performing a handful of ``from
      fabric.foo import bar`` calls.

* The undocumented `fab_quiet` option has been replaced by a much more granular
  set of output controls. For more info, see :doc:`../usage/output_controls`.


Changes from alpha 1 to alpha 2
===============================

The below list was generated by running ``git shortlog 0.9a1..0.9a2`` and then
manually sifting through and editing the resulting commit messages. This will
probably occur for the rest of the alphas and betas; we hope to use
Sphinx-specific methods of documenting changes once the final release is out
the door.

* Various minor tweaks to the (still in-progress) documentation, including one
  thanks to Curt Micol.
  
* Added a number of TODO items based on user feedback (thanks!)

* Host information now available in granular form (user, host, port) in the
  env dict, alongside the full ``user@host:port`` host string.

* Parsing of host strings is now more lenient when examining the username
  (e.g. hyphens.)

* User/host info no longer cleared out between commands.

* Tweaked ``setup.py`` to use ``find_packages``. Thanks to Pat McNerthney.

* Added 'capture' argument to `~fabric.operations.local` to allow local
  interactive tasks.

* Reversed default value of `~fabric.operations.local`'s ``show_stderr``
  kwarg; local stderr now prints by default instead of being hidden by
  default.

* Various internal fabfile tweaks.


Changes from alpha 2 to alpha 3
===============================

* Lots of updates to the documentation and TODO

* Added contrib.files with a handful of file-centric subroutines

* Added contrib.console for console UI stuff (so far, just `confirm`)

* Reworked config file mechanisms a bit, added CLI flag for setting it.

* Output controls (including CLI args, documentation) have been added

* Test coverage tweaked and grown a small amount (thanks in part to Peter
  Ellis)

* Roles overhauled/fixed (more like hosts now)

* Changed ``--list`` linewrap behavior to truncate instead.

* Make private key passphrase prompting more obvious to users.

* Add ``pty`` option to `sudo`. Thanks to José Muanis for the tip-off re: get_pty()

* Add CLI argument for setting the shell used in commands (thanks to Steve Steiner)

* Only load host keys when ``env.reject_unknown_keys`` is True. Thanks to Pat
  McNerthney.

* And many, many additional bugfixes and behavioral tweaks too small to merit
  cluttering up this list! Thanks as always to everyone who contributed
  bugfixes, feedback and/or patches.


Changes from alpha 3 to beta 1
==============================

This is closer to being a straight dump of the Git changelog than the previous
sections; apologies for the overall change in tense.

* Add autodocs for fabric.contrib.console.

* Minor cleanup to package init and setup.py.

* Handle exceptions with strerror attributes that are None instead of strings.

* contrib.files.append may now take a list of strings if desired.

* Straighten out how prompt() deals with trailing whitespace

* Add 'cd' context manager.

* Update upload_template to correctly handle backing up target directories.

* upload_template() can now use Jinja2 if it's installed and user asks for it.

* Handle case where remote host SSH key doesn't match known_hosts.

* Fix race condition in run/sudo.

* Start fledgling FAQ; extended pty option to run(); related doc tweaks.

* Bring local() in line with run()/sudo() in terms of .failed attribute.

* Add dollar-sign backslash escaping to run/sudo.

* Add FAQ question re: backgrounding processes.

* Extend some of put()'s niceties to get(), plus docstring/comment updates

* Add debug output of chosen fabfile for troubleshooting fabfile discovery.

* Fix Python path bug which sometimes caused Fabric's internal fabfile to
  pre-empt user's fabfile during load phase.

* Gracefully handle "display" for tasks with no docstring.

* Fix edge case that comes up during some auth/prompt situations.

* Handle carriage returns in output_thread correctly. Thanks to Brian Rosner.


Changes from beta 1 to release candidate 1
==========================================

As with the previous changelog, this is also mostly a dump of the Git log. We
promise that future changelogs will be more verbose :)

* Near-total overhaul and expansion of documentation (this is the big one!)
  Other mentions of documentation in this list are items deserving their own
  mention, e.g. FAQ updates.
* Add FAQ question re: passphrase/password prompt
* Vendorized Paramiko: it is now included in our distribution and is no longer
  an external dependency, at least until upstream fixes a nasty 1.7.5 bug.
* Fix #34: switch upload_template to use mkstemp (also removes Python 2.5.2+
  dependency -- now works on 2.5.0 and up)
* Fix #62 by escaping backticks.
* Replace "ls" with "test" in exists()
* Fixes #50. Thanks to Alex Koshelev for the patch.
* ``local``'s return value now exhibits ``.return_code``.
* Abort on bad role names instead of blowing up.
* Turn off DeprecationWarning when importing paramiko.
* Attempted fix re #32 (dropped output)
* Update role/host initialization logic (was missing some edge cases)
* Add note to install docs re: PyCrypto on win32.
* Add FAQ item re: changing env.shell.
* Rest of TODO migrated to tickets.
* ``fab test`` (when in source tree) now uses doctests.
* Add note to compatibility page re: fab_quiet.
* Update local() to honor context_managers.cd()

Changes from release candidate 1 to final release
=================================================

* Fixed the `~fabric.contrib.files.sed` docstring to accurately reflect which
  ``sed`` options it uses.
* Various changes to internal fabfile, version mechanisms, and other
  non-user-facing things.
