Commit 81b3facd authored by Agustin Henze's avatar Agustin Henze

Imported Upstream version 0.24.0

parent 16b2fe6f
repo: 200226df084a54a53b025a8884c7e79d6baa6b70
node: 2b86bed3ddc10ee62213c6ae0d12176fc2abf67c
branch: default
tag: 0.24.0
syntax:glob
*.pyc
.coverage*
__pycache__
.doit.db*
.strace
.pytest-incremental*
pytest.ini
tests/data/*
dist
MANIFEST
revision.txt
temp
_build
.svn
pip-log.txt
doit.egg-info
doc/tutorial/python-logo.gif
doc/tutorial/foo.tar
doc/tutorial/hello.txt
doc/tutorial/file0.txt
doc/tutorial/file1.txt
doc/tutorial/file2.txt
doc/tutorial/edit
doc/tutorial/*.o
doc/tutorial/foo
doc/tutorial/foo.txt
doc/tutorial/my_input.txt
doc/tutorial/task1
build
12fec534781fe60d630660870da760a1f9cbb019 0.6.0
1eada965eac5b29d9b507d0ba457c1e1ea8d60bb 0.15.0
21dacd171f845fd699898785fa1327c986717a6d 0.3
2ecea7431f57bb394f336f91ddb87eef6684f412 0.9.0
436c29203846041d63ba84deef27ddf1a7a588df 0.14.0
45006f439edc4f8a579fb1e5c3e55c51b9e3577b 0.8.0
76fd918fe794910aae439bec6a7ba94137cdd35c 0.2.0
8a066c8c71eff611d0eddf5d35cc192c89563e95 0.4.0
998728cb8ee06ab0fe354c97f9fddb9dc5f45b69 0.7.0
a614c2d1079663eb6c070b9d48e0492d38f77ea3 0.10.0
a94c65d8b92b9710f9c7b53b3bdd50b7845ceb3e 0.5
d5705767ef7376c22f36ca9884d1c60bdfe8d65c 0.5.1
e83cd6773714fbb9f70088cc01983967e3ebc606 0.13.0
fa3c9bd7b85e8e47e0c4d511ea0ca8c4db83b295 0.11.0
d9e9d149fe1d82ea1d7ffdbec70c335f3bcb750c 0.16.0
488a3f8f67129ce6f662232812f0b4aab88d3cd5 0.17
1570e3451de3cab31d83b0bb31075fc7dea8ad6a 0.17.0
488a3f8f67129ce6f662232812f0b4aab88d3cd5 0.17
0000000000000000000000000000000000000000 0.17
205514449f5dd535382d74f78e02db6868c8ff38 0.18.0
24aa9a77da97939dc4a55d4c564f17aea0294133 0.18.1
1af307bbf5ed5e427c7c8020b3ee0095e07e6c08 0.19.0
3f9eeef60b64980a72ff5c2a7a3d71efa6231b4e git/master
ed193cd36470aab7d7774f4303a7cee0a104b605 git/master
0000000000000000000000000000000000000000 git/master
ed193cd36470aab7d7774f4303a7cee0a104b605 git/master
0000000000000000000000000000000000000000 git/master
df48c0f87e46a87612750107deaaf758c06fc826 0.20.0
f88c849abf94fdb11f845a165c9da68211a70ef4 0.21.0
d3e6bccd1d49ca050e775c6eb0f42fb023dee4a6 0.21.1
a9f0c8b86853e1ea83266d5e7600ab0710ccc88c 0.22.0
748e0215ba3d153d6cb95614d4b2a0e24f246c9f 0.22.1
cddeafe5998033ba9a9b8d3f5c2f26967c27151d 0.23.0
78af1a48c00a5b299bba6438cf19b100251888b3 0.24.0
......@@ -2,12 +2,17 @@ language: python
python:
- "2.6"
- "2.7"
- "3.1"
- "3.2"
- "3.3"
- 'pypy'
before_install:
- sudo apt-get install strace
install:
- "pip install . --use-mirrors"
# See https://github.com/travis-ci/travis-cookbooks/issues/155
- sudo rm -rf /dev/shm && sudo ln -s /run/shm /dev/shm
branches:
only:
......@@ -15,10 +20,6 @@ branches:
- test
before_script:
- if [[ $TRAVIS_PYTHON_VERSION == '3.1' ]]; then 2to3 --write --nobackups .; fi
- if [[ $TRAVIS_PYTHON_VERSION == '3.2' ]]; then 2to3 --write --nobackups .; fi
script: py.test
notifications:
......
......@@ -3,6 +3,18 @@
Changes
=======
0.24.0
======================
- reporter added `initialize()`
- cmd `list`: added option `--template`
- dodo.py can specify minimum required doit version with DOIT_CONFIG['minversion']
- #62: added the absolute path from which doit is invoked `doit.initial_workdir`
- fix #36: added method `isatty()` to `action.Writer`
- added command `tabcompletion` for bash and zsh
- fix #56: allow python actions to have default values for task parameters
0.23.0 (*2013-09-20*)
======================
......
Metadata-Version: 1.1
Name: doit
Version: 0.23.0
Summary: doit - Automation Tool
Home-page: http://pydoit.org
Author: Eduardo Naufel Schettino
Author-email: schettino72@gmail.com
License: MIT
Description:
`doit` comes from the idea of bringing the power of build-tools
to execute any kind of **task**
`website/docs <http://pydoit.org>`_
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Operating System :: POSIX
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.2
Classifier: Programming Language :: Python :: 3.3
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: System Administrators
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: Software Development :: Testing
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Scientific/Engineering
......@@ -13,10 +13,10 @@ execute any kind of task
Project Details
===============
- Project management on bitbucket - https://bitbucket.org/schettino72/doit
- Source code & Project management on bitbucket - https://bitbucket.org/schettino72/doit
- Website & docs - http://pydoit.org
- Discussion group - https://groups.google.com/forum/#!forum/python-doit
- Official github mirror at - https://github.com/schettino72/doit
license
=======
......
see
https://bitbucket.org/schettino72/doit/issues?status=new&status=open
0.X
----------
......
# bash completion for doit
# auto-generate by `doit tabcomplention`
# to activate it you need to 'source' the generate script
# $ source <generated-script>
# reference => http://www.debian-administration.org/articles/317
# patch => http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=711879
_doit()
{
local cur prev words cword basetask sub_cmds tasks i dodof
COMPREPLY=()
COMPREPLY=() # contains list of words with suitable completion
# remove colon from word separator list because doit uses colon on task names
_get_comp_words_by_ref -n : cur prev words cword
# list of doit sub-commands
sub_cmds="help run clean list forget ignore auto dumpdb"
# list of sub-commands
sub_cmds="dumpdb run help strace auto list ignore clean tabcompletion forget"
# options that take file/dir as values should complete file-system
......@@ -48,18 +53,18 @@ _doit()
# get task list
# if it there is colon it is getting a subtask...
# if it there is colon it is getting a subtask, complete only subtask names
if [[ "$cur" == *:* ]]; then
# extract base task name (remove everything after colon)
basetask=${cur%:*}
# sub-tasks
tasks=$(doit list --file="$dodof" --quiet --all ${basetask})
tasks=$(doit list --file="$dodof" --quiet --all ${basetask} 2>/dev/null)
COMPREPLY=( $(compgen -W "${tasks}" -- ${cur}) )
__ltrim_colon_completions "$cur"
return 0
# without colons get only top tasks
else
tasks=$(doit list --file="$dodof" --quiet)
tasks=$(doit list --file="$dodof" --quiet 2>/dev/null)
fi
......@@ -70,6 +75,12 @@ _doit()
return 0
fi
# if command is help complete with tasks or sub-commands
if [[ ${words[1]} == "help" ]] ; then
COMPREPLY=( $(compgen -W "${sub_cmds} ${tasks}" -- ${cur}) )
return 0
fi
# if there is already one parameter match only tasks (no commands)
COMPREPLY=( $(compgen -W "${tasks}" -- ${cur}) )
......
......@@ -166,6 +166,59 @@ be specified for a group of "sub-tasks".
.. literalinclude:: tutorial/empty_subtasks.py
.. _tabcompletion:
tabcompletion
----------------
This command creates a completion for bash or zsh.
The generated script is written on stdout.
bash
^^^^^^
To use a completion script you need to `source` it first.
.. code-block:: console
$ doit tabcompletion > bash_completion_doit
$ source bash_completion_doit
zsh
^^^^^
zsh completion scripts should be placed in a folder in the "autoload" path.
.. code-block:: sh
# add folder with completion scripts
fpath=(~/.zsh/completion $fpath)
# Use modern completion system
autoload -Uz compinit
compinit
.. code-block:: console
$ doit tabcompletion --shell zsh > _doit
$ cp _doit ~/.zsh/tabcompletion/_doit
hard-coding tasks
^^^^^^^^^^^^^^^^^^^^
If you are creating an application based on `doit`
or if you tasks take a long time to load you may create
a completion script that includes the list of tasks
from your dodo.py.
.. code-block:: console
$ my_app tabcompletion --hardcode-tasks > _my_app
dumpdb
--------
......
......@@ -225,6 +225,19 @@ The option --output-file/-o let you output the result to a file.
$ doit --output-file result.txt
initial_workdir
-----------------
When `doit` executes by default it will use the location of `dodo.py`
as the current working directory (unless --dir is specified).
The value of `doit.initial_workdir` will contain the path from where
`doit` was invoked from.
This can be used for example set which tasks will be executed:
.. literalinclude:: tutorial/initial_workdir.py
config
--------
......@@ -251,6 +264,29 @@ You need to check `doit_cmd.py <https://bitbucket.org/schettino72/doit/src/tip/d
The parameters `--file` and `--dir` can not be used on config because they control how the dodo file itself is loaded.
minversion
^^^^^^^^^^^^
`minversion` can be used to specify the minimum/oldest `doit` version
that can be used with a `dodo.py` file.
For example if your `dodo.py` makes use of a feature added at `doit X`
and distribute it. If another user who tries this `dodo.py` with a version
older that `X`, doit will display an error warning the user to update `doit`.
.. code-block:: console
DOIT_CONFIG = {
'minversion': '0.24.0',
}
.. note::
This feature was added on `doit` 0.24.0.
Older Versions will not check or display error messages.
returned value
------------------
......@@ -262,14 +298,3 @@ returned value
* 3 => error before task execution starts
(in this case the reporter is not used)
bash completion
-----------------
Bash completion for `doit` to auto-complete task names is available at `bash_completion_doit <https://bitbucket.org/schettino72/doit/src/tip/bash_completion_doit>`_ . To activate it:
.. code-block:: console
$ source <path-to-file>/bash_completion_doit
......@@ -230,3 +230,18 @@ WORDBREAKS
Popen
popen
CmdAction's
workdir
isatty
'minversion'
minversion
tabcompletion
zsh
autoload
fpath
cp
app
hardcode
Uz
compinit
'0
0'
......@@ -10,3 +10,22 @@ A simple dictionary is actually the most flexible representation.
It is possible to create different interfaces on top of it.
Check this `blog post <http://blog.schettino72.net/posts/doit-task-creation.html>`_
for some examples.
`dodo.py` file itself should be a `file_dep` for all tasks
-----------------------------------------------------------
If I edit my `dodo.py` file and re-run *doit*,
and my tasks are otherwise up-to-date, the modified tasks are not re-run.
While developing your tasks it is recommended
to use ``doit forget`` after you change your tasks
or use ``doit --always-run``.
In case you really want, you will need to explicitly
add the `dodo.py` in `file_dep` of your tasks manually.
If `dodo.py` was an implicit `file_dep`:
* how would you disable it?
* should imported files from your `dodo.py` also be a `file_dep`?
......@@ -76,9 +76,6 @@ but often you want to create this metadata programmatically.
def my_task_action(dependencies):
# do something
# or with a object
MyCustomTask2(my_param)
Other features...
......@@ -98,6 +95,11 @@ Other features...
process output can be completely customized through *reporters*
(:ref:`more <reporter>`)
.. topic:: tab-completion
tab-completion for commands/task (supports bash and zsh)
(:ref:`more <tabcompletion>`)
.. topic:: extensible
......@@ -148,7 +150,7 @@ Status
This blog `post <http://schettino72.wordpress.com/2008/04/14/doit-a-build-tool-tale/>`_ explains how everything started in 2008.
`doit` is under active development. Version 0.23 released on 2013-09.
`doit` is under active development. Version 0.24 released on 2013-11.
`doit` core features are quite stable. So if there is no recent development,
it does NOT mean `doit` is not being maintained...
......@@ -156,7 +158,8 @@ The project has 100% unit-test code coverage
and kept with *zero* bugs in the tracker.
Development is done based on real world use cases.
If I don't need a feature and nobody never asked for it, it is not implemented ;)
If I don't need a feature and nobody never asked/implemented it,
it is not implemented ;)
It is well designed and has a very small code base
so adding new features isn't hard.
......
......@@ -187,23 +187,6 @@ This is useful to write some generic/reusable task-creators.
. t1
avoiding empty sub-tasks
^^^^^^^^^^^^^^^^^^^^^^^^^^
If you are not sure sub-tasks will be created for a given ``basename``
but you want to make sure that a task exist,
you can yield a sub-task with ``name`` equal to ``None``.
This can also used to set the task ``doc`` and ``watch`` attribute.
.. literalinclude:: tutorial/empty_subtasks.py
.. code-block:: console
$ doit
$ doit list
do_x docs for X
sub-tasks
---------
......@@ -226,6 +209,23 @@ additional field ``name``.
avoiding empty sub-tasks
^^^^^^^^^^^^^^^^^^^^^^^^^^
If you are not sure sub-tasks will be created for a given ``basename``
but you want to make sure that a task exist,
you can yield a sub-task with ``name`` equal to ``None``.
This can also used to set the task ``doc`` and ``watch`` attribute.
.. literalinclude:: tutorial/empty_subtasks.py
.. code-block:: console
$ doit
$ doit list
do_x docs for X
Dependencies & Targets
-------------------------
......
### README
# Sample to test doit.initial_workdir
# First create a folder named 'sub1'.
# Invoking doit from the root folder will execute both tasks 'base' and 'sub1'.
# Invoking 'doit -k' from path 'sub1' will execute only task 'sub1'
##################
import os
import doit
DOIT_CONFIG = {
'verbosity': 2,
'default_tasks': None, # all by default
}
# change default tasks based on dir from where doit was run
sub1_dir = os.path.join(os.path.dirname(__file__), 'sub1')
if doit.initial_workdir == sub1_dir:
DOIT_CONFIG['default_tasks'] = ['sub1']
def task_base():
return {'actions': ['echo root']}
def task_sub1():
return {'actions': ['echo sub1']}
......@@ -9,6 +9,7 @@ import pytest
from doit.tools import create_folder
DOIT_CONFIG = {
'minversion': '0.24.dev0',
'default_tasks': ['checker', 'ut'],
# 'backend': 'sqlite3',
}
......@@ -33,7 +34,7 @@ def task_checker():
yield {'actions': ["pyflakes %(dependencies)s"],
'name':module,
'file_dep':(module,),
'task_dep':['_pyflakes_builtins'],
'setup':['_pyflakes_builtins'],
'title': (lambda task: task.name)}
def run_test(test):
......
......@@ -23,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
__version__ = (0, 23, 0)
__version__ = (0, 24, 0)
# used to save variable values passed from command line
......@@ -38,3 +38,8 @@ def get_var(name, default=None):
def set_var(name, value):
CMDLINE_VARS[name] = value
# Directory path from where doit was executed.
# Set by loader, to be used on dodo.py by users.
initial_workdir = None
......@@ -45,13 +45,14 @@ class BaseAction(object):
except TypeError:
argspec = inspect.getargspec(func.__call__)
# use task meta information as extra_args
extra_args = {
meta_args = {
'task': task,
'targets': task.targets,
'dependencies': task.file_dep,
'changed': task.dep_changed,
}
extra_args = dict(meta_args)
# tasks parameter options
extra_args.update(task.options)
kwargs = kwargs.copy()
......@@ -63,10 +64,10 @@ class BaseAction(object):
# it is forbidden to use default values for this arguments
# because the user might be unware of this magic.
if (argspec.defaults and
if (key in meta_args and argspec.defaults and
len(argspec.defaults) > (len(argspec.args) - (arg_pos+1))):
msg = ("%s.%s: '%s' argument default value not allowed "
"(reserved by doit)"
msg = ("Task %s, action %s(): The argument '%s' is not "
"allowed to have a default value (reserved by doit)"
% (task.name, func.__name__, key))
raise InvalidTask(msg)
......@@ -102,7 +103,7 @@ class CmdAction(BaseAction):
**pkwargs): #pylint: disable=W0231
for forbidden in ('stdout', 'stderr'):
if forbidden in pkwargs:
msg = "CmdAction can't take param named '{}'."
msg = "CmdAction can't take param named '{0}'."
raise InvalidTask(msg.format(forbidden))
self._action = action
self.task = task
......@@ -247,7 +248,18 @@ class Writer(object):
"""write to many streams"""
def __init__(self, *writers):
"""@param writers - file stream like objects"""
self.writers = writers
self.writers = []
self._isatty = True
for writer in writers:
self.add_writer(writer)
def add_writer(self, stream, isatty=None):
"""adds a stream to the list of writers
@param isatty: (bool) if specified overwrites real isatty from stream
"""
self.writers.append(stream)
isatty = stream.isatty() if (isatty is None) else isatty
self._isatty = self._isatty and isatty
def write(self, text):
"""write 'text' to all streams"""
......@@ -259,6 +271,9 @@ class Writer(object):
for stream in self.writers:
stream.flush()
def isatty(self):
return self._isatty
class PythonAction(BaseAction):
"""Python action. Execute a python callable.
......@@ -323,18 +338,20 @@ class PythonAction(BaseAction):
# set std stream
old_stdout = sys.stdout
output = StringIO()
out_writer = Writer()
# capture output but preserve isatty() from original stream
out_writer.add_writer(output, old_stdout.isatty())
if out:
out_writer.add_writer(out)
sys.stdout = out_writer
old_stderr = sys.stderr
errput = StringIO()
out_list = [output]
if out:
out_list.append(out)
err_list = [errput]
err_writer = Writer()
err_writer.add_writer(errput, old_stderr.isatty())
if err:
err_list.append(err)
sys.stdout = Writer(*out_list)
sys.stderr = Writer(*err_list)
err_writer.add_writer(err)
sys.stderr = err_writer
kwargs = self._prepare_kwargs()
......
import inspect
import sys
import doit
from .cmdparse import CmdOption, CmdParse
from .exceptions import InvalidCommand
from .exceptions import InvalidCommand, InvalidDodoFile
from .dependency import backend_map
from . import loader
def version_tuple(ver_in):
"""convert a version string or tuple into a 3-element tuple with ints
Any part that is not a number (dev0, a2, b4) will be converted to -1
"""
result = []
parts = ver_in.split('.') if isinstance(ver_in, str) else ver_in
for rev in parts:
try:
result.append(int(rev))
except:
result.append(-1)
assert len(result) == 3
return result
class Command(object):
"""third-party should subclass this for commands that do no use tasks
......@@ -199,6 +215,7 @@ class DoitCmdBase(Command):
def __init__(self, task_loader=None, dep_file=None, backend=None,
config=None, task_list=None, sel_tasks=None, outstream=None):
"""this initializer is usually just used on tests"""
# FIXME 'or TaskLoader()' below is hack for tests
self._loader = task_loader or TaskLoader()
Command.__init__(self)
# TODO: helper to test code should not be here
......@@ -226,6 +243,16 @@ class DoitCmdBase(Command):
args)
self.sel_tasks = args or self.config.get('default_tasks')
# check minversion
minversion = self.config.get('minversion')
if minversion:
if version_tuple(minversion) > version_tuple(doit.__version__):
msg = ('Please update doit. '
'Minimum version required is {required}. '
'You are using {actual}. ')
raise InvalidDodoFile(msg.format(required=minversion,
actual=doit.__version__))
# merge config values into params
params.update_defaults(self.config)
self.dep_file = params['dep_file']
......
This diff is collapsed.
......@@ -90,7 +90,7 @@ watch:
class Help(DoitCmdBase):
doc_purpose = "show help"
doc_usage = ""
doc_usage = "[TASK] [COMMAND]"
doc_description = None
@staticmethod
......
<
from .cmd_base import DoitCmdBase, check_tasks_exist, subtasks_iter
opt_listall = {'name': 'subtasks',
'short':'',
'long': 'all',
'type': bool,
'default': False,
'help': "list include all sub-tasks from dodo file"
}
opt_list_quiet = {'name': 'quiet',
'short': 'q',
'long': 'quiet',
'type': bool,
'default': False,
'help': 'print just task name (less verbose than default)'}
opt_list_status = {'name': 'status',
'short': 's',
'long': 'status',
'type': bool,
'default': False,
'help': 'print task status (R)un, (U)p-to-date, (I)gnored'}
opt_list_private = {'name': 'private',
'short': 'p',
'long': 'private',
'type': bool,
'default': False,
'help': "print private tasks (start with '_')"}
opt_list_dependencies = {'name': 'list_deps',
'short': '',
'long': 'deps',
'type': bool,
'default': False,
'help': ("print list of dependencies "
"(file dependencies only)")
}
opt_listall = {
'name': 'subtasks',
'short':'',
'long': 'all',
'type': bool,