Repository: opsdroid/opsdroid

Issue:
Loader static methods
There are some functions at the beginning of the loader file. These should be private static methods in the class.



Discussion:

Resolving patch:
diff --git a/opsdroid/loader.py b/opsdroid/loader.py
--- a/opsdroid/loader.py
+++ b/opsdroid/loader.py
@@ -10,59 +10,6 @@
     DEFAULT_GIT_URL, MODULES_DIRECTORY, DEFAULT_MODULE_BRANCH)
 
 
-def import_module(config):
-    """Import module namespace as variable and return it."""
-    try:
-        module = importlib.import_module(
-            config["path"] + "." + config["name"])
-        logging.debug("Loading " + config["type"] + ": " + config["name"])
-        return module
-    except ImportError as error:
-        logging.error("Failed to load " + config["type"] +
-                      " " + config["name"])
-        logging.error(error)
-        return None
-
-
-def check_cache(config):
-    """Remove module if 'no-cache' set in config."""
-    if "no-cache" in config \
-            and config["no-cache"] \
-            and os.path.isdir(config["install_path"]):
-        logging.debug("'no-cache' set, removing " + config["install_path"])
-        shutil.rmtree(config["install_path"])
-
-
-def build_module_path(path_type, config):
-    """Generate the module path from name and type."""
-    if path_type == "import":
-        return MODULES_DIRECTORY + "." + config["type"] + "." + config["name"]
-    elif path_type == "install":
-        return MODULES_DIRECTORY + "/" + config["type"] + "/" + config["name"]
-
-
-def git_clone(git_url, install_path, branch):
-    """Clone a git repo to a location and wait for finish."""
-    process = subprocess.Popen(["git", "clone", "-b", branch,
-                                git_url, install_path], shell=False,
-                               stdout=subprocess.PIPE,
-                               stderr=subprocess.PIPE)
-    process.wait()
-
-
-def pip_install_deps(requirements_path):
-    """Pip install a requirements.txt file and wait for finish."""
-    process = subprocess.Popen(["pip", "install", "-r", requirements_path],
-                               shell=False,
-                               stdout=subprocess.PIPE,
-                               stderr=subprocess.PIPE)
-    for output in process.communicate():
-        if output != "":
-            for line in output.splitlines():
-                logging.debug(str(line).strip())
-    process.wait()
-
-
 class Loader:
     """Class to load in config and modules."""
 
@@ -71,6 +18,61 @@ def __init__(self, opsdroid):
         self.opsdroid = opsdroid
         logging.debug("Loaded loader")
 
+    @staticmethod
+    def import_module(config):
+        """Import module namespace as variable and return it."""
+        try:
+            module = importlib.import_module(
+                config["path"] + "." + config["name"])
+            logging.debug("Loading " + config["type"] + ": " + config["name"])
+            return module
+        except ImportError as error:
+            logging.error("Failed to load " + config["type"] +
+                          " " + config["name"])
+            logging.error(error)
+            return None
+
+    @staticmethod
+    def check_cache(config):
+        """Remove module if 'no-cache' set in config."""
+        if "no-cache" in config \
+                and config["no-cache"] \
+                and os.path.isdir(config["install_path"]):
+            logging.debug("'no-cache' set, removing " + config["install_path"])
+            shutil.rmtree(config["install_path"])
+
+    @staticmethod
+    def build_module_path(path_type, config):
+        """Generate the module path from name and type."""
+        if path_type == "import":
+            return MODULES_DIRECTORY + "." + config["type"] + \
+                        "." + config["name"]
+        elif path_type == "install":
+            return MODULES_DIRECTORY + "/" + config["type"] + \
+                        "/" + config["name"]
+
+    @staticmethod
+    def git_clone(git_url, install_path, branch):
+        """Clone a git repo to a location and wait for finish."""
+        process = subprocess.Popen(["git", "clone", "-b", branch,
+                                    git_url, install_path], shell=False,
+                                   stdout=subprocess.PIPE,
+                                   stderr=subprocess.PIPE)
+        process.wait()
+
+    @staticmethod
+    def pip_install_deps(requirements_path):
+        """Pip install a requirements.txt file and wait for finish."""
+        process = subprocess.Popen(["pip", "install", "-r", requirements_path],
+                                   shell=False,
+                                   stdout=subprocess.PIPE,
+                                   stderr=subprocess.PIPE)
+        for output in process.communicate():
+            if output != "":
+                for line in output.splitlines():
+                    logging.debug(str(line).strip())
+        process.wait()
+
     def load_config_file(self, config_paths):
         """Load a yaml config file from path."""
         config_path = ""
@@ -134,19 +136,19 @@ def _load_modules(self, modules_type, modules):
             config = {} if config is None else config
             config["name"] = module_name
             config["type"] = modules_type
-            config["path"] = build_module_path("import", config)
-            config["install_path"] = build_module_path("install", config)
+            config["path"] = self.build_module_path("import", config)
+            config["install_path"] = self.build_module_path("install", config)
             if "branch" not in config:
                 config["branch"] = DEFAULT_MODULE_BRANCH
 
             # Remove module for reinstall if no-cache set
-            check_cache(config)
+            self.check_cache(config)
 
             # Install module
             self._install_module(config)
 
             # Import module
-            module = import_module(config)
+            module = self.import_module(config)
             if module is not None:
                 loaded_modules.append({
                     "module": module,
@@ -181,11 +183,12 @@ def _install_module(self, config):
             if any(prefix in git_url for prefix in ["http", "https", "ssh"]):
                 # TODO Test if url or ssh path exists
                 # TODO Handle github authentication
-                git_clone(git_url, config["install_path"], config["branch"])
+                self.git_clone(git_url, config["install_path"],
+                               config["branch"])
             else:
                 if os.path.isdir(git_url):
-                    git_clone(git_url, config["install_path"],
-                              config["branch"])
+                    self.git_clone(git_url, config["install_path"],
+                                   config["branch"])
                 else:
                     logging.debug("Could not find local git repo " + git_url)
 
@@ -197,4 +200,5 @@ def _install_module(self, config):
 
             # Install module dependancies
             if os.path.isfile(config["install_path"] + "/requirements.txt"):
-                pip_install_deps(config["install_path"] + "/requirements.txt")
+                self.pip_install_deps(config["install_path"] +
+                                      "/requirements.txt")


Test patch:
diff --git a/tests/test_loader.py b/tests/test_loader.py
--- a/tests/test_loader.py
+++ b/tests/test_loader.py
@@ -48,28 +48,30 @@ def test_setup_modules(self):
 
     def test_git_clone(self):
         self.reset_subprocess_mocks()
-        ld.git_clone("https://github.com/rmccue/test-repository.git",
-                     "/tmp/test", "master")
+        ld.Loader.git_clone("https://github.com/rmccue/test-repository.git",
+                            "/tmp/test", "master")
         self.assertNotEqual(len(sys.modules['subprocess'].mock_calls), 0)
 
     def test_pip_install_deps(self):
         self.reset_subprocess_mocks()
-        ld.pip_install_deps("/path/to/some/file.txt")
+        ld.Loader.pip_install_deps("/path/to/some/file.txt")
         self.assertNotEqual(len(sys.modules['subprocess'].mock_calls), 0)
 
     def test_build_module_path(self):
         config = {}
         config["type"] = "test"
         config["name"] = "test"
-        self.assertIn("test.test", ld.build_module_path("import", config))
-        self.assertIn("test/test", ld.build_module_path("install", config))
+        self.assertIn("test.test",
+                      ld.Loader.build_module_path("import", config))
+        self.assertIn("test/test",
+                      ld.Loader.build_module_path("install", config))
 
     def test_check_cache_removes(self):
         config = {}
         config["no-cache"] = True
         config['install_path'] = "/tmp/test/module"
         os.makedirs(config['install_path'])
-        ld.check_cache(config)
+        ld.Loader.check_cache(config)
         self.assertFalse(os.path.isdir(config["install_path"]))
 
     def test_check_cache_leaves(self):
@@ -77,7 +79,7 @@ def test_check_cache_leaves(self):
         config["no-cache"] = False
         config['install_path'] = "/tmp/test/module"
         os.makedirs(config['install_path'])
-        ld.check_cache(config)
+        ld.Loader.check_cache(config)
         self.assertTrue(os.path.isdir(config["install_path"]))
         shutil.rmtree(config["install_path"])
 
@@ -87,7 +89,7 @@ def test_import_module(self):
         config["name"] = "path"
         config["type"] = "system"
 
-        module = ld.import_module(config)
+        module = ld.Loader.import_module(config)
         self.assertIsInstance(module, ModuleType)
 
     def test_import_module_failure(self):
@@ -96,7 +98,7 @@ def test_import_module_failure(self):
         config["name"] = "module"
         config["type"] = "broken"
 
-        module = ld.import_module(config)
+        module = ld.Loader.import_module(config)
         self.assertEqual(module, None)
 
     def test_load_config(self):