setup.py: make libbe._version optional.
[be.git] / libbe / command / base.py
index 11835eebe332e8dad074109661fdd92ff65db073..61404c1d42e2bd27331a05611581c181e5047cb7 100644 (file)
@@ -1,32 +1,36 @@
-# Copyright (C) 2009-2011 Chris Ball <cjb@laptop.org>
+# Copyright (C) 2009-2012 Chris Ball <cjb@laptop.org>
+#                         Phil Schumm <philschumm@gmail.com>
 #                         Robert Lehmann <mail@robertlehmann.de>
-#                         W. Trevor King <wking@drexel.edu>
+#                         W. Trevor King <wking@tremily.us>
 #
 # This file is part of Bugs Everywhere.
 #
-# Bugs Everywhere is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation, either version 2 of the License, or (at your
-# option) any later version.
+# Bugs Everywhere is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 2 of the License, or (at your option) any
+# later version.
 #
 # Bugs Everywhere is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
 #
-# You should have received a copy of the GNU General Public License
-# along with Bugs Everywhere.  If not, see <http://www.gnu.org/licenses/>.
+# You should have received a copy of the GNU General Public License along with
+# Bugs Everywhere.  If not, see <http://www.gnu.org/licenses/>.
 
 import codecs
 import optparse
 import os.path
 import StringIO
 import sys
+import urlparse
+import yaml
 
 import libbe
 import libbe.storage
 import libbe.ui.util.user
 import libbe.util.encoding
+import libbe.util.http
 import libbe.util.plugin
 
 
@@ -260,11 +264,13 @@ class Command (object):
     <BLANKLINE>
     A detailed help message.
     """
+    user_agent = 'BE-HTTP-Command'
 
     name = 'command'
 
-    def __init__(self, ui=None):
+    def __init__(self, ui=None, server=None):
         self.ui = ui # calling user-interface
+        self.server = server # location of eventual execution
         self.status = None
         self.result = None
         self.restrict_file_access = True
@@ -290,7 +296,10 @@ class Command (object):
         else:
             params.pop('complete')
 
-        self.status = self._run(**params)
+        if self.server:
+            self.status = self._run_remote(**params)
+        else:
+            self.status = self._run(**params)
         return self.status
 
     def _parse_options_args(self, options=None, args=None):
@@ -338,6 +347,17 @@ class Command (object):
     def _run(self, **kwargs):
         raise NotImplementedError
 
+    def _run_remote(self, **kwargs):
+        data = yaml.safe_dump({
+                'command': self.name,
+                'parameters': kwargs,
+                })
+        url = urlparse.urljoin(self.server, 'run')
+        page,final_url,info = libbe.util.http.get_post_url(
+            url=url, get=False, data=data, agent=self.user_agent)
+        self.stdout.write(page)
+        return 0
+
     def help(self, *args):
         return '\n\n'.join([self.usage(),
                             self._option_help(),
@@ -482,8 +502,7 @@ class StringInputOutput (InputOutput):
 
     def get_stdout(self):
         ret = self.stdout.getvalue()
-        self.stdout = StringIO.StringIO() # clear stdout for next read
-        self.stdin.encoding = 'utf-8'
+        self.stdout.truncate(size=0)
         return ret
 
 class UnconnectedStorageGetter (object):
@@ -503,7 +522,7 @@ class StorageCallbacks (object):
     def setup_command(self, command):
         command._get_unconnected_storage = self.get_unconnected_storage
         command._get_storage = self.get_storage
-        command._get_bugdir = self.get_bugdir
+        command._get_bugdirs = self.get_bugdirs
 
     def get_unconnected_storage(self):
         """
@@ -536,15 +555,20 @@ class StorageCallbacks (object):
     def set_storage(self, storage):
         self._storage = storage
 
-    def get_bugdir(self):
+    def get_bugdirs(self):
         """Callback for use by commands that need it."""
-        if not hasattr(self, '_bugdir'):
-            self._bugdir = libbe.bugdir.BugDir(self.get_storage(),
-                                               from_storage=True)
-        return self._bugdir
-
-    def set_bugdir(self, bugdir):
-        self._bugdir = bugdir
+        if not hasattr(self, '_bugdirs'):
+            storage = self.get_storage()
+            self._bugdirs = dict(
+                (uuid, libbe.bugdir.BugDir(
+                        storage=storage,
+                        uuid=uuid,
+                        from_storage=True))
+                for uuid in storage.children())
+        return self._bugdirs
+
+    def set_bugdirs(self, bugdirs):
+        self._bugdirs = bugdirs
 
     def cleanup(self):
         if hasattr(self, '_storage'):
@@ -566,11 +590,11 @@ class UserInterface (object):
         return command.run(options, args)
 
     def setup_command(self, command):
-        if command.ui == None:
+        if command.ui is None:
             command.ui = self
-        if self.io != None:
+        if self.io is not None:
             self.io.setup_command(command)
-        if self.storage_callbacks != None:
+        if self.storage_callbacks is not None:
             self.storage_callbacks.setup_command(command)        
         command.restrict_file_access = self.restrict_file_access
         command._get_user_id = self._get_user_id
@@ -583,5 +607,6 @@ class UserInterface (object):
         return self._user_id
 
     def cleanup(self):
-        self.storage_callbacks.cleanup()
+        if self.storage_callbacks is not None:
+            self.storage_callbacks.cleanup()
         self.io.cleanup()