Moved script logic to its own class
authorFred <fmcell@gmail.com>
Sat, 18 May 2013 11:48:57 +0000 (19:48 +0800)
committerFred <fmcell@gmail.com>
Sat, 18 May 2013 11:48:57 +0000 (19:48 +0800)
lib/exceptions.py
lib/moodle.py
lib/scripts.py [new file with mode: 0644]

index 599695e..1ca645f 100644 (file)
@@ -47,6 +47,10 @@ class ConfigFileCouldNotBeSaved(Exception):
     pass
 
 
+class ConflictInScriptName(Exception):
+    pass
+
+
 class CreateException(Exception):
     pass
 
@@ -57,3 +61,7 @@ class InstallException(Exception):
 
 class ScriptNotFound(Exception):
     pass
+
+
+class UnsupportedScript(Exception):
+    pass
index 0e120f5..ad51a40 100644 (file)
@@ -26,7 +26,6 @@ import os
 import re
 import logging
 import shutil
-import subprocess
 
 from tools import process, parseBranch
 from db import DB
@@ -34,6 +33,7 @@ from config import Conf
 from git import Git
 from exceptions import ScriptNotFound, InstallException
 from jira import Jira
+from scripts import Scripts
 
 C = Conf()
 
@@ -540,41 +540,7 @@ class Moodle(object):
 
     def runScript(self, scriptname, **kwargs):
         """Runs a script on the instance"""
-        supported = ['php']
-        directories = ['~/.moodle-sdk']
-        if C.get('dirs.moodle') != None:
-            directories.insert(0, C.get('dirs.moodle'))
-        directories.append('/etc/moodle-sdk')
-        directories.append(os.path.join(os.path.dirname(__file__), '..'))
-
-        # Loop over each directory in order of preference.
-        for directory in directories:
-            script = None
-            type = None
-
-            f = os.path.expanduser(os.path.join(directory, 'scripts', scriptname))
-            if os.path.isfile(f) and scriptname.rsplit('.', 1)[1] in supported:
-                script = f
-                type = scriptname.rsplit('.', 1)[1]
-            else:
-                for ext in supported:
-                    if os.path.isfile(f + '.' + ext):
-                        script = f + '.' + ext
-                        type = ext
-                        break
-            # Exit the loop if the script has been found.
-            if script != None and type != None:
-                break
-
-        if not script:
-            raise ScriptNotFound('Could not find the script, or format not supported')
-
-        if type == 'php':
-            dest = os.path.join(self.get('path'), 'mdkrun.php')
-            shutil.copyfile(script, dest)
-            result = self.cli('mdkrun.php', **kwargs)
-            os.remove(dest)
-            return result[0]
+        return Scripts.run(scriptname, self.get('path'), cmdkwargs=kwargs)
 
     def update(self, remote=None):
         """Update the instance from the remote"""
diff --git a/lib/scripts.py b/lib/scripts.py
new file mode 100644 (file)
index 0000000..4d16660
--- /dev/null
@@ -0,0 +1,135 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Moodle Development Kit
+
+Copyright (c) 2013 Frédéric Massart - FMCorz.net
+
+This program 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 3 of the License, or
+(at your option) any later version.
+
+This program 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.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+http://github.com/FMCorz/mdk
+"""
+
+import os
+import shutil
+from tools import process
+from config import Conf
+from exceptions import ScriptNotFound, ConflictInScriptName, UnsupportedScript
+
+C = Conf()
+
+
+class Scripts(object):
+
+    _supported = ['php']
+    _dirs = None
+    _list = None
+
+    @classmethod
+    def dirs(cls):
+        """Return the directories containing scripts, in priority order"""
+
+        if not cls._dirs:
+            dirs = ['~/.moodle-sdk']
+            if C.get('dirs.moodle') != None:
+                dirs.insert(0, C.get('dirs.moodle'))
+            dirs.append('/etc/moodle-sdk')
+            dirs.append(os.path.join(os.path.dirname(__file__), '..'))
+
+            i = 0
+            for d in dirs:
+                dirs[i] = os.path.expanduser(os.path.join(d, 'scripts'))
+                i += 1
+
+            cls._dirs = dirs
+
+        return cls._dirs
+
+    @classmethod
+    def list(cls):
+        """Return a dict where keys are the name of the scripts
+           and the value is the directory in which the script is stored"""
+
+        if not cls._list:
+            scripts = {}
+
+            # Walk through the directories, in reverse to get the higher
+            # priority last.
+            dirs = cls.dirs()
+            dirs.reverse()
+            for d in dirs:
+
+                if not os.path.isdir(d):
+                    continue
+
+                # For each file found in the directory.
+                l = os.listdir(d)
+                for f in l:
+
+                    # Check if supported format.
+                    supported = False
+                    for ext in cls._supported:
+                        if f.endswith(u'.' + ext):
+                            supported = True
+                            break
+
+                    if supported:
+                        scripts[f] = d
+
+            cls._list = scripts
+
+        return cls._list
+
+    @classmethod
+    def find(cls, script):
+        """Return the path to a script"""
+
+        lst = cls.list()
+        cli = None
+        if script in lst.keys():
+            cli = os.path.join(lst[script], script)
+        else:
+            for ext in cls._supported:
+                found = 0
+                scriptFile = script + u'.' + ext
+                if scriptFile in lst.keys():
+                    found += 1
+
+            if found > 1:
+                raise ConflictInScriptName('The script name conflicts with other ones')
+            elif found == 1:
+                cli = os.path.join(lst[scriptFile], scriptFile)
+
+        if not cli:
+            raise ScriptNotFound('Script not found')
+
+        return cli
+
+    @classmethod
+    def run(cls, script, path, cmdkwargs={}):
+        """Executes a script at in a certain directory"""
+
+        cli = cls.find(script)
+        if cli.endswith('.php'):
+            dest = os.path.join(path, 'mdkscriptrun.php')
+            shutil.copyfile(cli, dest)
+
+            cmd = '%s %s' % (C.get('php'), dest)
+            result = process(cmd, cwd=path, **cmdkwargs)
+            os.remove(dest)
+        else:
+            raise UnsupportedScript('Script not supported')
+
+        return result[0]