From 3d2ed9b221a121912bed3699e0ca2f19775d993d Mon Sep 17 00:00:00 2001
From: Bohuslav Kabrda <bkabrda@redhat.com>
Date: Thu, 24 Oct 2013 11:34:50 +0200
Subject: [PATCH] Introduce task assistants

---
 README.rst                                         |  8 ++++-
 devassistant/actions.py                            | 15 ++++++++--
 devassistant/bin.py                                | 14 +++++++--
 devassistant/cache.py                              |  1 +
 devassistant/settings.py                           |  2 +-
 docs/assistant-roles.txt                           |  6 ++--
 docs/brief-intro.txt                               |  8 ++++-
 docs/developer_documentation/devassistant_core.rst |  5 +++-
 .../yaml_assistant_reference.rst                   | 35 ++++++++++------------
 docs/user_documentation.rst                        | 23 ++++++++++++--
 test/test_cache.py                                 |  1 +
 11 files changed, 85 insertions(+), 33 deletions(-)

diff --git a/README.rst b/README.rst
index 01ba470..4fc8767 100644
--- a/README.rst
+++ b/README.rst
@@ -28,12 +28,18 @@ DevAssistant also allows you to work with a previously created project, for exam
 
   $ da mod eclipse # run in project dir or use -p to specify path
 
-Last but not least, DevAssistant allows you to prepare environment for executing arbitrary tasks or developing upstream projects (either using "custom" assistant for projects previously created by DevAssistant or using specific assistant for specific projects):
+With DevAssistant, you can also prepare environment for developing upstream projects - either using project-specific assistants or using "custom" assistant for arbitrary projects (even those not created by DevAssistant):
 
 .. code:: sh
 
   $ da prep custom -u scm_url -p directory_to_save_to
 
+Last but not least, DevAssistant allows you to perform arbitrary tasks not related to a specific project:
+
+.. code:: sh
+
+  $ da task <TODO:NOTHING YET>
+
 For full documentation, see http://doc.devassistant.org/
 
 To start developing, do:
diff --git a/devassistant/actions.py b/devassistant/actions.py
index 146bb54..4270fec 100644
--- a/devassistant/actions.py
+++ b/devassistant/actions.py
@@ -1,3 +1,5 @@
+from devassistant import settings
+
 actions = {}
 
 def register_action(action):
@@ -39,9 +41,12 @@ class HelpAction(Action):
             format_type: type of formatting for nice output, see format_text for possible values
         """
         # we will justify the action names (and assistant types) to the same width
-        just = max(len('crt'), len('mod'), len('prep'), *map(lambda x: len(x), actions)) + 2
+        just = max(
+                max(*map(lambda x: len(x), settings.ASSISTANT_ROLES)),
+                max(*map(lambda x: len(x), actions))
+               ) + 2
         text = ['You can either run assistants with:']
-        text.append(cls.format_text('da [--debug] {crt,mod,prep} [ASSISTANT [ARGUMENTS]] ...',
+        text.append(cls.format_text('da [--debug] {crt,mod,prep,task} [ASSISTANT [ARGUMENTS]] ...',
                                     'bold',
                                     format_type))
         text.append('')
@@ -55,7 +60,11 @@ class HelpAction(Action):
                                            just,
                                            format_type))
         text.append(cls.format_action_line('prep',
-                                           'used for preparing environment for upstream projects and various tasks',
+                                           'used for preparing environment for upstream projects',
+                                            just,
+                                            format_type))
+        text.append(cls.format_action_line('task',
+                                           'used for performing custom tasks not related to a specific project',
                                             just,
                                             format_type))
         text.append('')
diff --git a/devassistant/bin.py b/devassistant/bin.py
index 0dde875..083e670 100644
--- a/devassistant/bin.py
+++ b/devassistant/bin.py
@@ -35,12 +35,22 @@ class PreparerAssistant(ExecutableAssistant):
 
     name = 'prep'
     fullname = 'Prepare Environment'
-    description = 'Prepare environment for upstream projects or various tasks with DevAssistant.'
+    description = 'Prepare environment for upstream projects with DevAssistant.'
+
+class TaskAssistant(ExecutableAssistant):
+    def get_subassistants(self):
+        sa = yaml_assistant_loader.YamlAssistantLoader.get_assistants(superassistants=[self])
+        return sa
+
+    name = 'task'
+    fullname = 'Non-project Task'
+    description = 'Perform a custom task not related to a specific project with DevAssistant.'
 
 class TopAssistant(assistant_base.AssistantBase):
     _assistants = []
     def get_subassistants(self):
         # cache assistants to always return the same instances
         if not self._assistants:
-            self._assistants = [CreatorAssistant(), ModifierAssistant(), PreparerAssistant()]
+            self._assistants = [CreatorAssistant(), ModifierAssistant(),
+                                PreparerAssistant(), TaskAssistant()]
         return self._assistants
diff --git a/devassistant/cache.py b/devassistant/cache.py
index 603ecb8..d1cc0c1 100644
--- a/devassistant/cache.py
+++ b/devassistant/cache.py
@@ -38,6 +38,7 @@ class Cache(object):
             'subhierarchy': {'d': {...}},
      'mod': {...},
      'prep': {...},
+     'task': {...},
      # version of devassistant that cache has been created with
      'version': VERSION}
     """
diff --git a/devassistant/settings.py b/devassistant/settings.py
index f4ed8f0..4b0dac4 100644
--- a/devassistant/settings.py
+++ b/devassistant/settings.py
@@ -20,5 +20,5 @@ CACHE_FILE = os.path.expanduser('~/.devassistant/.cache.yaml')
 DATA_DIRECTORIES = [os.path.join(os.path.dirname(__file__), 'data'),
                     '/usr/local/share/devassistant',
                     os.path.expanduser('~/.devassistant')]
-ASSISTANT_ROLES=['crt', 'mod', 'prep']
+ASSISTANT_ROLES=['crt', 'mod', 'prep', 'task']
 DEFAULT_ASSISTANT_ROLE = 'crt'
diff --git a/docs/assistant-roles.txt b/docs/assistant-roles.txt
index 54023f7..1cde9f2 100644
--- a/docs/assistant-roles.txt
+++ b/docs/assistant-roles.txt
@@ -1,11 +1,13 @@
-There are three assistant roles:
+There are four assistant roles:
 
 creator (``crt`` in short)
   creates new projects
 modifier (``mod`` in short)
   modifies existing projects
 preparer (``prep`` in short)
-  prepares environment for development of upstream project or custom task
+  prepares environment for development of upstream projects
+task (``task`` in short)
+  performs arbitrary tasks not related to a specific project
 
 The main purpose of having roles is separating different types of tasks.
 It would be confusing to have e.g. ``python django`` assistant (that
diff --git a/docs/brief-intro.txt b/docs/brief-intro.txt
index 692a2b2..cc551c8 100644
--- a/docs/brief-intro.txt
+++ b/docs/brief-intro.txt
@@ -16,10 +16,16 @@ DevAssistant also allows you to work with a previously created project, for exam
 
    $ da mod eclipse # run in project dir or use -p to specify path
 
-Last but not least, DevAssistant allows you to prepare environment for executing arbitrary tasks or developing upstream projects (either using "custom" assistant for projects previously created by DevAssistant or using specific assistant for specific projects)::
+With DevAssistant, you can also prepare environment for developing upstream projects - either using project-specific assistants or using "custom" assistant for arbitrary projects (even those not created by DevAssistant)::
 
    $ da prep custom custom -u scm_url
 
 **Warning:** The ``custom`` assistant executes custom pieces of code from
 ``.devassistant`` file of the project. Therefore you have to be extra careful
 and use this **only with projects whose authors you trust**.
+
+Last but not least, DevAssistant allows you to perform arbitrary tasks not related to a specific project:
+
+.. code:: sh
+
+  $ da task <TODO:NOTHING YET>
diff --git a/docs/developer_documentation/devassistant_core.rst b/docs/developer_documentation/devassistant_core.rst
index 8bd3cf1..0fa2778 100644
--- a/docs/developer_documentation/devassistant_core.rst
+++ b/docs/developer_documentation/devassistant_core.rst
@@ -23,15 +23,18 @@ Each load path entry has this structure::
      crt/
      mod/
      prep/
+     task/
    files/
      crt/
      mod/
      prep/
+     task/
      snippets/
    icons/
      crt/
      mod/
      prep/
+     task/
    snippets/
 
 Icons under ``icons`` directory and files in ``files`` directory "copy"
@@ -49,7 +52,7 @@ order "system", "local", "user".
 
 When DevAssistant starts up, it loads all assistants from all these paths. It
 assumes, that Creator assistants are located under ``crt`` subdirectories
-the same applies to Modifier (``mod``) and Preparer (``prep``) assistants.
+the same applies to Modifier (``mod``), Preparer (``prep``) and Task (``task``) assistants.
 
 For example, loading process for Creator assistants looks like this:
 
diff --git a/docs/developer_documentation/yaml_assistant_reference.rst b/docs/developer_documentation/yaml_assistant_reference.rst
index 00999c0..1817ebc 100644
--- a/docs/developer_documentation/yaml_assistant_reference.rst
+++ b/docs/developer_documentation/yaml_assistant_reference.rst
@@ -24,26 +24,16 @@ at `assistants in our Github repo`_.
 
 Assistant Roles
 ---------------
-There are three types of assistants:
-
-Creator
-  creator assistants are meant to create new projects from scratch, they're
-  accessed using ``da`` binary
-Modifier
-  modifier assistants are used for modifying existing projects previously
-  created by DevAssistant
-Preparer
-  preparer assistants are used for setting up environment for already existing
-  projects (located e.g. at remote SCM etc.) that may or may not have been
-  creating by DevAssistant
+
+For list and description of assistant roles see :ref:`assistant_roles_devel`.
 
 The role is implied by assistant location in one of the load path directories,
 as mentioned in :ref:`assistants_loading_mechanism`.
 
 All the rules mentioned in this document apply to all types of assistants,
-with exception of sections :ref:`modifier_assistants_ref` and
-:ref:`preparer_assistants_ref` that talk about specifics of Modifier, resp.
-Preparer assistants.
+with exception of sections :ref:`modifier_assistants_ref`, :ref:`preparer_assistants_ref` and
+:ref:`task_assistants_ref` that talk about specifics of Modifier, resp. Preparer, resp. Task
+assistants.
 
 Assistant Name
 --------------
@@ -437,11 +427,18 @@ The special rules below **only apply if you use dda_t in pre_run section**.
 Preparer Assistants
 -------------------
 
-Preparer assistants are assistants that are supposed to set up environment for
-executing arbitrary tasks or prepare environment and checkout existing upstream
-projects (possibly using their ``.devassistant`` file, if they have it).
-Preparers must be placed under ``prep`` subdirectory of one of the load
+Preparer assistants are assistants that are supposed to checkout sources of upstream
+projects and set up environment for them (possibly utilizing their ``.devassistant`` file,
+if they have one). Preparers must be placed under ``prep`` subdirectory of one of the load
 paths, as mentioned in :ref:`assistants_loading_mechanism`.
 
 Preparer assistants commonly utilize the ``dda_dependencies`` and ``dda_run``
 commands in ``run`` section.
+
+.. _task_assistants_ref:
+
+Task Assistants
+---------------
+
+Task assistants are supposed to carry out arbitrary task that are not related to a specific
+project. <TODO>
diff --git a/docs/user_documentation.rst b/docs/user_documentation.rst
index f712aa7..a6183cb 100644
--- a/docs/user_documentation.rst
+++ b/docs/user_documentation.rst
@@ -82,12 +82,16 @@ Preparing Environment
 ~~~~~~~~~~~~~~~~~~~~~
 
 DevAssistant can set up environment and install dependencies for
-executing aribtrary tasks or development of already existing project located
-in a remote SCM (e.g. Github). For custom projects created
-by DevAssistant, you can use the ``custom`` assistant::
+development of already existing project located
+in a remote SCM (e.g. Github). For custom projects you can use the ``custom`` assistant.
+Note that for projects that don't have ``.devassistant`` file, this will just checkout
+the sources::
 
    $ da prep custom -u scm_url
 
+**Warning:** The ``custom`` assistant executes custom pieces of code from ``.devassistant`` file,
+so use this only for projects whose upstreams you trust.
+
 The plan is to also include assistants for well known and largely developed projects
 (that, of course, don't contain ``.devassistant`` file). So in future you should be
 able to do something like::
@@ -97,6 +101,14 @@ able to do something like::
 and it should do everything needed to get you started developing OpenStack in a way
 that others do. But this is still somewhere in the future...
 
+Tasks
+~~~~~
+
+The last piece of functionality is performing arbitrary tasks that are not related to a specific
+projects. E.g.::
+
+   $ da task <TODO:NOTHING YET>
+
 Custom Actions
 ~~~~~~~~~~~~~~
 There are also some custom actions besides ``crt``, ``mod`` and ``prep``. For
@@ -173,3 +185,8 @@ Preparing
 
 - Custom - checkout a custom previously created project from SCM (git only so far) and
   install needed dependencies
+
+Tasks
+~~~~~
+
+<TODO: NOTHING YET>
diff --git a/test/test_cache.py b/test/test_cache.py
index 4cca166..ae4ddc2 100644
--- a/test/test_cache.py
+++ b/test/test_cache.py
@@ -58,6 +58,7 @@ correct_cache = \
                                           'subhierarchy': {}}}}},
  'mod': {},
  'prep': {},
+ 'task': {},
  'version': VERSION}
 
 class TestCache(object):
-- 
1.8.3.1

