<commit_before>======================
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` 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
broad 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 simply refer to e.g. ``env.host_string`` (or ``env.host``,
``env.user`` and so forth) when building strings.

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
====================================<commit_msg>Minor extra tweak to compat docs<commit_after>======================
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` 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
broad 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
====================================
{'fraction_non_alphanumeric': 0.10272663245799377, 'fraction_numerical': 0.005433142167220043, 'mean_word_length': 3.8019323671497585, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 8, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2093666', 'n_tokens_mistral': 2637, 'n_tokens_neox': 2478, 'n_words': 1461}