Hi everybody!

This is my first post here. I'm using fabric together with vagrant and since I 
have additional files, like the Vagrantfile, provisioning scripts etc. that 
made me eventually wrap my fabfile into a Python package (egg). So, there I 
have now a Python script named to call this package functionality, say 
"test.py", that actually wraps "fab -f fabile.py" with the fabfile sitting 
inside the package by using subprocess.Popen(cmd, shell=False, ...). I have 
attached a minimal version, using tasks running with 'local'.

The first observation is that output for commands containing flags like '-l' is 
wrapped after 80 characters in my terminal although it is actually wider than 
that:

$ python test.py -l
running: fab -f test.py -l
Test executing fabric tasks wrapped on the command-line vs. programmatically.

Available commands:

    date            Print the current date.
    date_confirmed  Also print the current date, but now with some interactiv...

$ fab -f test.py -l

Test executing fabric tasks wrapped on the command-line vs. programmatically.

Available commands:

    date            Print the current date.
    date_confirmed  Also print the current date, but now with some interactive 
confirmation and long docstring.

But funnily, the -d flag works fine (is not wrapped):

$ python test.py -d date_confirmed
running: fab -f test.py -d date_confirmed
Displaying detailed information for task 'date_confirmed':

    Also print the current date, but now with some interactive confirmation and 
long docstring.
    Arguments:

Apart from this running tasks worked quite well until I realized issues with 
fabric functions like fabric.contrib.console.confirm which interact with the 
user on the command-line. This makes my call to subprocess.Popen block:

$ python test.py date
running: fab -f test.py date
Mo  7 Apr 2014 15:26:17 CEST
[localhost] local: date

Done.

$ python test.py date_confirmed
running: fab -f test.py date_confirmed
^CTraceback (most recent call last):
  File "test.py", line 42, in <module>
    print(p.stdout.read().strip())
KeyboardInterrupt

I tried then to work around this by calling the fabric tasks programmatically 
using the "execute" function, which sort of works (here switched on with an 
--exec option):

$ python test.py --exec date
executing: date
[localhost] local: date
Mo  7 Apr 2014 15:24:34 CEST

$ python test.py --exec date_confirmed
executing: date_confirmed
Really? [y/N] y
[localhost] local: date
Mo  7 Apr 2014 15:24:38 CEST

But then I don't seem to find a way to execute several tasks chained as when 
given directly on the command-line for "fab", more or less in order not to 
loose shared data in the fabric environment.

So I wonder: what is the recommended best practice for wrapping fabric inside 
another tool/package? Or is there a way to make Popen not block on interactive 
functions like confirm? I have attached a simple script illustrating what I 
mean (used in the snippets above), running trivial local tasks without chaining.

Thanks in advance,

Dinu

PS: Sorry if this is a FAQ! If so I've managed to not find it.

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

"""
Test executing fabric tasks wrapped on the command-line vs. programmatically.
"""

import sys
from subprocess import PIPE, Popen

from fabric.decorators import task
from fabric.api import local, execute
from fabric.contrib.console import confirm
from fabric.main import parse_arguments

@task
def date():
    "Print the current date."
    local('date')

@task
def date_confirmed():
    "Also print the current date, but now with some interactive confirmation and long docstring."
    if confirm("Really?", default=False):
        local('date')

if __name__ == "__main__":
    try:
        argv = sys.argv[1:]
    except IndexError:
        sys.exit()

    # check --exec option and remove it if given
    do_exec = '--exec' in argv
    if '--exec' in argv:
        argv.remove('--exec')

    if not do_exec:
        cmd = ['fab', '-f', __file__] + argv
        print('running: %s' % ' '.join(cmd))
        p = Popen(cmd, shell=False, stdout=PIPE, stderr=PIPE)
        print(p.stdout.read().strip())
    else:
        args = parse_arguments(argv)
        for a in args:
            name, args, kwargs = a[:3]
            print('executing: %s' % name)
            execute(eval(name), *args, **kwargs)

_______________________________________________
Fab-user mailing list
Fab-user@nongnu.org
https://lists.nongnu.org/mailman/listinfo/fab-user

Reply via email to