Get rid of factory json files in benchmark_runner
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Jun 2015 03:47:24 +0000 (03:47 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Jun 2015 03:47:24 +0000 (03:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=146175

Patch by Dewei Zhu <dewei_zhu@apple.com> on 2015-06-22
Reviewed by Ryosuke Niwa.

Get rid of factory json files in benchmark_runner and refactoring the code.

* Scripts/webkitpy/benchmark_runner/benchmark_builder/__init__.py:
(benchmark_builder_loader):
* Scripts/webkitpy/benchmark_runner/benchmark_builder/benchmark_builder_factory.py:
(BenchmarkBuilderFactory):
* Scripts/webkitpy/benchmark_runner/benchmark_builder/benchmark_builders.json: Removed.
* Scripts/webkitpy/benchmark_runner/benchmark_builder/generic_benchmark_builder.py:
(GenericBenchmarkBuilder):
* Scripts/webkitpy/benchmark_runner/benchmark_runner.py:
(BenchmarkRunner.__init__):
(BenchmarkRunner.execute):
* Scripts/webkitpy/benchmark_runner/browser_driver/__init__.py:
(browser_driver_loader):
* Scripts/webkitpy/benchmark_runner/browser_driver/browser_driver.py:
(BrowserDriver):
* Scripts/webkitpy/benchmark_runner/browser_driver/browser_driver_factory.py:
(BrowserDriverFactory):
(BrowserDriverFactory.available_platforms):
(BrowserDriverFactory.available_browsers):
(BrowserDriverFactory.add_browser_driver):
(BrowserDriverFactory.create):
* Scripts/webkitpy/benchmark_runner/browser_driver/browser_drivers.json: Removed.
* Scripts/webkitpy/benchmark_runner/browser_driver/osx_browser_driver.py:
(OSXBrowserDriver):
(OSXBrowserDriver.prepareEnv):
(OSXBrowserDriver.terminateProcesses):
(OSXBrowserDriver.screenSize):
* Scripts/webkitpy/benchmark_runner/browser_driver/osx_chrome_driver.py:
(OSXChromeDriver):
(OSXChromeCanaryDriver):
* Scripts/webkitpy/benchmark_runner/browser_driver/osx_firefox_driver.py:
(OSXFirefoxDriver):
(OSXFirefoxNightlyDriver):
* Scripts/webkitpy/benchmark_runner/browser_driver/osx_safari_driver.py:
(OSXSafariDriver):
* Scripts/webkitpy/benchmark_runner/generic_factory.py:
(GenericFactory.create):
(GenericFactory.add):
(GenericFactory.iterateGetItem): Deleted.
* Scripts/webkitpy/benchmark_runner/http_server_driver/__init__.py:
(http_server_driver_loader):
* Scripts/webkitpy/benchmark_runner/http_server_driver/http_server_driver.py:
(HTTPServerDriver):
* Scripts/webkitpy/benchmark_runner/http_server_driver/http_server_driver_factory.py:
(HTTPServerDriverFactory):
* Scripts/webkitpy/benchmark_runner/http_server_driver/http_server_drivers.json: Removed.
* Scripts/webkitpy/benchmark_runner/http_server_driver/simple_http_server_driver.py:
(SimpleHTTPServerDriver):
* Scripts/webkitpy/benchmark_runner/utils.py:
(is_subclass):
(load_subclasses):
(ModuleNotFoundError): Deleted.
(loadModule): Deleted.
(loadJSONFromFile): Deleted.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@185859 268f45cc-cd09-0410-ab3c-d52691b4dbfc

21 files changed:
Tools/ChangeLog
Tools/Scripts/webkitpy/benchmark_runner/benchmark_builder/__init__.py
Tools/Scripts/webkitpy/benchmark_runner/benchmark_builder/benchmark_builder_factory.py
Tools/Scripts/webkitpy/benchmark_runner/benchmark_builder/benchmark_builders.json [deleted file]
Tools/Scripts/webkitpy/benchmark_runner/benchmark_builder/generic_benchmark_builder.py
Tools/Scripts/webkitpy/benchmark_runner/benchmark_runner.py
Tools/Scripts/webkitpy/benchmark_runner/browser_driver/__init__.py
Tools/Scripts/webkitpy/benchmark_runner/browser_driver/browser_driver.py
Tools/Scripts/webkitpy/benchmark_runner/browser_driver/browser_driver_factory.py
Tools/Scripts/webkitpy/benchmark_runner/browser_driver/browser_drivers.json [deleted file]
Tools/Scripts/webkitpy/benchmark_runner/browser_driver/osx_browser_driver.py
Tools/Scripts/webkitpy/benchmark_runner/browser_driver/osx_chrome_driver.py
Tools/Scripts/webkitpy/benchmark_runner/browser_driver/osx_firefox_driver.py
Tools/Scripts/webkitpy/benchmark_runner/browser_driver/osx_safari_driver.py
Tools/Scripts/webkitpy/benchmark_runner/generic_factory.py
Tools/Scripts/webkitpy/benchmark_runner/http_server_driver/__init__.py
Tools/Scripts/webkitpy/benchmark_runner/http_server_driver/http_server_driver.py
Tools/Scripts/webkitpy/benchmark_runner/http_server_driver/http_server_driver_factory.py
Tools/Scripts/webkitpy/benchmark_runner/http_server_driver/http_server_drivers.json [deleted file]
Tools/Scripts/webkitpy/benchmark_runner/http_server_driver/simple_http_server_driver.py
Tools/Scripts/webkitpy/benchmark_runner/utils.py

index be59369..36d99b8 100644 (file)
@@ -1,3 +1,66 @@
+2015-06-22  Dewei Zhu  <dewei_zhu@apple.com>
+
+        Get rid of factory json files in benchmark_runner
+        https://bugs.webkit.org/show_bug.cgi?id=146175
+
+        Reviewed by Ryosuke Niwa.
+
+        Get rid of factory json files in benchmark_runner and refactoring the code.
+
+        * Scripts/webkitpy/benchmark_runner/benchmark_builder/__init__.py:
+        (benchmark_builder_loader):
+        * Scripts/webkitpy/benchmark_runner/benchmark_builder/benchmark_builder_factory.py:
+        (BenchmarkBuilderFactory):
+        * Scripts/webkitpy/benchmark_runner/benchmark_builder/benchmark_builders.json: Removed.
+        * Scripts/webkitpy/benchmark_runner/benchmark_builder/generic_benchmark_builder.py:
+        (GenericBenchmarkBuilder):
+        * Scripts/webkitpy/benchmark_runner/benchmark_runner.py:
+        (BenchmarkRunner.__init__):
+        (BenchmarkRunner.execute):
+        * Scripts/webkitpy/benchmark_runner/browser_driver/__init__.py:
+        (browser_driver_loader):
+        * Scripts/webkitpy/benchmark_runner/browser_driver/browser_driver.py:
+        (BrowserDriver):
+        * Scripts/webkitpy/benchmark_runner/browser_driver/browser_driver_factory.py:
+        (BrowserDriverFactory):
+        (BrowserDriverFactory.available_platforms):
+        (BrowserDriverFactory.available_browsers):
+        (BrowserDriverFactory.add_browser_driver):
+        (BrowserDriverFactory.create):
+        * Scripts/webkitpy/benchmark_runner/browser_driver/browser_drivers.json: Removed.
+        * Scripts/webkitpy/benchmark_runner/browser_driver/osx_browser_driver.py:
+        (OSXBrowserDriver):
+        (OSXBrowserDriver.prepareEnv):
+        (OSXBrowserDriver.terminateProcesses):
+        (OSXBrowserDriver.screenSize):
+        * Scripts/webkitpy/benchmark_runner/browser_driver/osx_chrome_driver.py:
+        (OSXChromeDriver):
+        (OSXChromeCanaryDriver):
+        * Scripts/webkitpy/benchmark_runner/browser_driver/osx_firefox_driver.py:
+        (OSXFirefoxDriver):
+        (OSXFirefoxNightlyDriver):
+        * Scripts/webkitpy/benchmark_runner/browser_driver/osx_safari_driver.py:
+        (OSXSafariDriver):
+        * Scripts/webkitpy/benchmark_runner/generic_factory.py:
+        (GenericFactory.create):
+        (GenericFactory.add):
+        (GenericFactory.iterateGetItem): Deleted.
+        * Scripts/webkitpy/benchmark_runner/http_server_driver/__init__.py:
+        (http_server_driver_loader):
+        * Scripts/webkitpy/benchmark_runner/http_server_driver/http_server_driver.py:
+        (HTTPServerDriver):
+        * Scripts/webkitpy/benchmark_runner/http_server_driver/http_server_driver_factory.py:
+        (HTTPServerDriverFactory):
+        * Scripts/webkitpy/benchmark_runner/http_server_driver/http_server_drivers.json: Removed.
+        * Scripts/webkitpy/benchmark_runner/http_server_driver/simple_http_server_driver.py:
+        (SimpleHTTPServerDriver):
+        * Scripts/webkitpy/benchmark_runner/utils.py:
+        (is_subclass):
+        (load_subclasses):
+        (ModuleNotFoundError): Deleted.
+        (loadModule): Deleted.
+        (loadJSONFromFile): Deleted.
+
 2015-06-22  Simon Fraser  <simon.fraser@apple.com>
 
         Make it possible to enable incremental rendering suppression in MiniBrowser
index b376bf2..a32f002 100644 (file)
 # code in this file so that callers can opt-in as they want.  This also
 # allows different callers to choose different initialization code,
 # as necessary.
+import os
+
+from webkitpy.benchmark_runner.utils import load_subclasses
+from benchmark_builder_factory import BenchmarkBuilderFactory
+
+
+def benchmark_builder_loader(benchmark_builder_class):
+    if benchmark_builder_class.builder_name:
+        BenchmarkBuilderFactory.add(benchmark_builder_class.builder_name, benchmark_builder_class)
+
+
+load_subclasses(
+    dirname=os.path.dirname(os.path.abspath(__file__)),
+    base_class_name='GenericBenchmarkBuilder',
+    loader=benchmark_builder_loader)
index 9601d3f..c6200b9 100644 (file)
@@ -5,12 +5,8 @@ import json
 import os
 
 from webkitpy.benchmark_runner.generic_factory import GenericFactory
-from webkitpy.benchmark_runner.utils import loadJSONFromFile
-
-
-builderFileName = 'benchmark_builders.json'
 
 
 class BenchmarkBuilderFactory(GenericFactory):
 
-    products = loadJSONFromFile(os.path.join(os.path.dirname(__file__), builderFileName))
+    products = {}
diff --git a/Tools/Scripts/webkitpy/benchmark_runner/benchmark_builder/benchmark_builders.json b/Tools/Scripts/webkitpy/benchmark_runner/benchmark_builder/benchmark_builders.json
deleted file mode 100644 (file)
index 1f4bdf3..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-    "GenericBenchmarkBuilder": {
-        "filePath": "benchmark_builder.generic_benchmark_builder",
-        "moduleName": "GenericBenchmarkBuilder"
-    }
-}
index 0e0ac36..69e4e68 100644 (file)
@@ -16,6 +16,8 @@ _log = logging.getLogger(__name__)
 
 class GenericBenchmarkBuilder(object):
 
+    builder_name = 'GenericBenchmarkBuilder'
+
     def prepare(self, name, plan):
         self.name = name
         self.webRoot = tempfile.mkdtemp()
index 47e78bd..8105072 100644 (file)
@@ -16,7 +16,7 @@ from benchmark_builder.benchmark_builder_factory import BenchmarkBuilderFactory
 from benchmark_results import BenchmarkResults
 from browser_driver.browser_driver_factory import BrowserDriverFactory
 from http_server_driver.http_server_driver_factory import HTTPServerDriverFactory
-from utils import loadModule, getPathFromProjectRoot
+from utils import getPathFromProjectRoot
 from utils import timeout
 
 
@@ -37,8 +37,8 @@ class BenchmarkRunner(object):
                     self.plan['count'] = countOverride
                 if httpServerDriverOverride:
                     self.plan['http_server_driver'] = httpServerDriverOverride
-                self.browserDriver = BrowserDriverFactory.create([platform, browser])
-                self.httpServerDriver = HTTPServerDriverFactory.create([self.plan['http_server_driver']])
+                self.browserDriver = BrowserDriverFactory.create(platform, browser)
+                self.httpServerDriver = HTTPServerDriverFactory.create(self.plan['http_server_driver'])
                 self.httpServerDriver.setDeviceID(deviceID)
                 self.buildDir = os.path.abspath(buildDir) if buildDir else None
                 self.outputFile = outputFile
@@ -65,7 +65,7 @@ class BenchmarkRunner(object):
         _log.info('Start to execute the plan')
         _log.info('Start a new benchmark')
         results = []
-        self.benchmarkBuilder = BenchmarkBuilderFactory.create([self.plan['benchmark_builder']])
+        self.benchmarkBuilder = BenchmarkBuilderFactory.create(self.plan['benchmark_builder'])
 
         webRoot = self.benchmarkBuilder.prepare(self.planName, self.plan)
         for x in xrange(int(self.plan['count'])):
index b376bf2..013c265 100644 (file)
 # code in this file so that callers can opt-in as they want.  This also
 # allows different callers to choose different initialization code,
 # as necessary.
+import os
+
+from webkitpy.benchmark_runner.utils import load_subclasses
+from browser_driver_factory import BrowserDriverFactory
+
+
+def browser_driver_loader(browser_driver_class):
+    if browser_driver_class.platform and browser_driver_class.browser_name:
+        BrowserDriverFactory.add_browser_driver(browser_driver_class.platform, browser_driver_class.browser_name, browser_driver_class)
+
+
+load_subclasses(
+    dirname=os.path.dirname(os.path.abspath(__file__)),
+    base_class_name='BrowserDriver',
+    loader=browser_driver_loader)
index 437a8cb..0f56b83 100644 (file)
@@ -4,6 +4,8 @@ import abc
 
 
 class BrowserDriver(object):
+    platform = None
+    browser_name = None
 
     @abc.abstractmethod
     def prepareEnv(self, deviceID):
index a140ec0..7b255d7 100644 (file)
@@ -4,25 +4,30 @@ import logging
 import json
 import os
 
-from webkitpy.benchmark_runner.generic_factory import GenericFactory
-from webkitpy.benchmark_runner.utils import loadJSONFromFile
 
+class BrowserDriverFactory(object):
 
-driverFileName = 'browser_drivers.json'
+    browser_drivers = {}
+    platforms = set()
+    browsers = set()
 
 
-class BrowserDriverFactory(GenericFactory):
-
-    products = loadJSONFromFile(os.path.join(os.path.dirname(__file__), driverFileName))
-
     @classmethod
     def available_platforms(cls):
-        return cls.products.keys()
+        return list(cls.platforms)
 
     @classmethod
     def available_browsers(cls):
-        browsers = []
-        for platform in cls.products.values():
-            for browser in platform:
-                browsers.append(browser)
-        return browsers
+        return list(cls.browsers)
+
+    @classmethod
+    def add_browser_driver(cls, platform, browser_name, browser_driver_class):
+        cls.platforms.add(platform)
+        cls.browsers.add(browser_name)
+        if platform not in cls.browser_drivers:
+            cls.browser_drivers[platform] = {}
+        cls.browser_drivers[platform][browser_name] = browser_driver_class
+
+    @classmethod
+    def create(cls, platform, browser_name):
+        return cls.browser_drivers[platform][browser_name]()
diff --git a/Tools/Scripts/webkitpy/benchmark_runner/browser_driver/browser_drivers.json b/Tools/Scripts/webkitpy/benchmark_runner/browser_driver/browser_drivers.json
deleted file mode 100644 (file)
index e27cbff..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-    "osx": {
-        "chrome": {
-            "moduleName": "OSXChromeDriver", 
-            "filePath": "browser_driver.osx_chrome_driver"
-        },
-        "chrome-canary": {
-            "moduleName": "OSXChromeCanaryDriver", 
-            "filePath": "browser_driver.osx_chrome_driver"
-        },
-        "firefox": {
-            "moduleName": "OSXFirefoxDriver", 
-            "filePath": "browser_driver.osx_firefox_driver"
-        },
-        "firefox-nightly": {
-            "moduleName": "OSXFirefoxNightlyDriver", 
-            "filePath": "browser_driver.osx_firefox_driver"
-        },
-        "safari": {
-            "moduleName": "OSXSafariDriver", 
-            "filePath": "browser_driver.osx_safari_driver"
-        }
-    } 
-}
index 2dc7eaa..fa7ade1 100644 (file)
@@ -3,9 +3,6 @@ import logging
 import os
 import subprocess
 
-from AppKit import NSRunningApplication
-from AppKit import NSScreen
-from Quartz import CGWarpMouseCursorPosition
 from browser_driver import BrowserDriver
 
 
@@ -14,9 +11,11 @@ _log = logging.getLogger(__name__)
 
 class OSXBrowserDriver(BrowserDriver):
     bundleIdentifier = None
+    platform = 'osx'
 
     def prepareEnv(self, deviceID):
         self.closeBrowsers()
+        from Quartz import CGWarpMouseCursorPosition
         CGWarpMouseCursorPosition((10, 0))
 
     def closeBrowsers(self):
@@ -37,6 +36,7 @@ class OSXBrowserDriver(BrowserDriver):
     @classmethod
     def terminateProcesses(cls, bundleIdentifier):
         _log.info('Closing all terminating all processes with the bundle identifier %s' % bundleIdentifier)
+        from AppKit import NSRunningApplication
         processes = NSRunningApplication.runningApplicationsWithBundleIdentifier_(bundleIdentifier)
         for process in processes:
             process.terminate()
@@ -49,4 +49,5 @@ class OSXBrowserDriver(BrowserDriver):
 
     @classmethod
     def screenSize(cls):
+        from AppKit import NSScreen
         return NSScreen.mainScreen().frame().size
index 2d18827..437f10a 100644 (file)
@@ -13,6 +13,7 @@ _log = logging.getLogger(__name__)
 
 class OSXChromeDriver(OSXBrowserDriver):
     bundleIdentifier = 'com.google.Chrome'
+    browser_name = 'chrome'
 
     def launchUrl(self, url, browserBuildPath):
         self.launchProcess(buildDir=browserBuildPath, appName='Google Chrome.app', url=url, args=['--args', '--homepage', url, '--window-size={width},{height}'.format(width=int(self.screenSize().width), height=int(self.screenSize().height))])
@@ -20,6 +21,7 @@ class OSXChromeDriver(OSXBrowserDriver):
 
 class OSXChromeCanaryDriver(OSXBrowserDriver):
     bundleIdentifier = 'com.google.Chrome.canary'
+    browser_name = 'chrome-canary'
 
     def launchUrl(self, url, browserBuildPath):
         self.launchProcess(buildDir=browserBuildPath, appName='Google Chrome Canary.app', url=url, args=['--args', '--homepage', url, '--window-size={width},{height}'.format(width=int(self.screenSize().width), height=int(self.screenSize().height))])
index ab49c78..d061ee4 100644 (file)
@@ -13,6 +13,7 @@ _log = logging.getLogger(__name__)
 
 class OSXFirefoxDriver(OSXBrowserDriver):
     bundleIdentifier = 'org.mozilla.firefox'
+    browser_name = 'firefox'
 
     def launchUrl(self, url, browserBuildPath):
         self.launchProcess(buildDir=browserBuildPath, appName='Firefox.app', url=url, args=[url, '--args', '-width', str(int(self.screenSize().width)), '-height', str(int(self.screenSize().height))])
@@ -20,6 +21,7 @@ class OSXFirefoxDriver(OSXBrowserDriver):
 
 class OSXFirefoxNightlyDriver(OSXBrowserDriver):
     bundleIdentifier = 'org.mozilla.nightly'
+    browser_name = 'firefox-nightly'
 
     def launchUrl(self, url, browserBuildPath):
         self.launchProcess(buildDir=browserBuildPath, appName='FirefoxNightly.app', url=url, args=[url, '--args', '-width', str(int(self.screenSize().width)), '-height', str(int(self.screenSize().height))])
index 7442847..ca461ea 100644 (file)
@@ -15,6 +15,7 @@ _log = logging.getLogger(__name__)
 
 class OSXSafariDriver(OSXBrowserDriver):
     bundleIdentifier = 'com.apple.Safari'
+    browser_name = 'safari'
 
     def prepareEnv(self, deviceID):
         self.safariProcess = None
index cebecb4..bdff392 100644 (file)
@@ -3,8 +3,6 @@
 import logging
 import os
 
-from utils import loadModule, ModuleNotFoundError
-
 
 _log = logging.getLogger(__name__)
 
@@ -14,18 +12,9 @@ class GenericFactory(object):
     products = None
 
     @classmethod
-    def iterateGetItem(cls, options, keys):
-        ret = options
-        for key in keys:
-            try:
-                ret = ret.__getitem__(key)
-            except KeyError:
-                raise
-        return ret
+    def create(cls, description):
+        return cls.products[description]()
 
     @classmethod
-    def create(cls, descriptions):
-        try:
-            return loadModule(cls.iterateGetItem(cls.products, descriptions))()
-        except Exception:
-            raise
+    def add(cls, description, product):
+        cls.products[description] = product
index b376bf2..1a0d6bd 100644 (file)
 # code in this file so that callers can opt-in as they want.  This also
 # allows different callers to choose different initialization code,
 # as necessary.
+import os
+import imp
+
+from webkitpy.benchmark_runner.utils import load_subclasses
+from http_server_driver_factory import HTTPServerDriverFactory
+
+
+def http_server_driver_loader(http_server_driver_class):
+    if http_server_driver_class.name:
+        HTTPServerDriverFactory.add(http_server_driver_class.name, http_server_driver_class)
+
+
+load_subclasses(
+    dirname=os.path.dirname(os.path.abspath(__file__)),
+    base_class_name='HTTPServerDriver',
+    loader=http_server_driver_loader)
index 9d29c63..aa70190 100644 (file)
@@ -4,6 +4,7 @@ from abc import abstractmethod
 
 
 class HTTPServerDriver(object):
+    name = None
     @abstractmethod
     def serve(self, webRoot):
         pass
index f8e8506..810d954 100644 (file)
@@ -5,12 +5,7 @@ import json
 import os
 
 from webkitpy.benchmark_runner.generic_factory import GenericFactory
-from webkitpy.benchmark_runner.utils import loadJSONFromFile
-
-
-driverFileName = 'http_server_drivers.json'
 
 
 class HTTPServerDriverFactory(GenericFactory):
-
-    products = loadJSONFromFile(os.path.join(os.path.dirname(__file__), driverFileName))
+    products = {}
diff --git a/Tools/Scripts/webkitpy/benchmark_runner/http_server_driver/http_server_drivers.json b/Tools/Scripts/webkitpy/benchmark_runner/http_server_driver/http_server_drivers.json
deleted file mode 100644 (file)
index 6bb3bcd..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "SimpleHTTPServerDriver": {
-    "moduleName": "SimpleHTTPServerDriver", 
-    "filePath": "http_server_driver.simple_http_server_driver"
-  }
-}
index 50551e9..64955df 100644 (file)
@@ -18,6 +18,7 @@ class SimpleHTTPServerDriver(HTTPServerDriver):
 
     """This class depends on unix environment, need to be modified to achieve crossplatform compability
     """
+    name = 'SimpleHTTPServerDriver'
 
     def __init__(self):
         self.server_process = None
index bc324e2..985e2fd 100644 (file)
@@ -1,25 +1,33 @@
 #!/usr/bin/env python
 
-import json
+import imp
+import inspect
 import logging
 import os
 import signal
 import shutil
+import sys
 
 
 _log = logging.getLogger(__name__)
 
 
-class ModuleNotFoundError(Exception):
-    pass
+# Borrow following code from stackoverflow
+# Link: http://stackoverflow.com/questions/11461356/issubclass-returns-flase-on-the-same-class-imported-from-different-paths
+def is_subclass(child, parent_name):
+    return inspect.isclass(child) and parent_name in [cls.__name__ for cls in inspect.getmro(child)]
 
 
-def loadModule(moduleDesc):
-    try:
-        ret = getattr(__import__(moduleDesc['filePath'], globals(), locals(), moduleDesc['moduleName'], -1), moduleDesc['moduleName'])
-        return ret
-    except Exception as error:
-        raise ModuleNotFoundError('Error loading module (%s) with path(%s): {%s}' % (moduleDesc['moduleName'], moduleDesc['filePath'], error))
+def load_subclasses(dirname, base_class_name, loader):
+    for filename in os.listdir(dirname):
+        if not filename.endswith('.py') or filename in ['__init__.py']:
+            continue
+        module_name = filename[:-3]
+        module = imp.load_source(module_name, os.path.join(dirname, filename))
+        for item_name in dir(module):
+            item = getattr(module, item_name)
+            if is_subclass(item, base_class_name):
+                loader(item)
 
 
 def getPathFromProjectRoot(relativePathToProjectRoot):
@@ -29,15 +37,6 @@ def getPathFromProjectRoot(relativePathToProjectRoot):
     return os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), relativePathToProjectRoot))
 
 
-def loadJSONFromFile(filePath):
-    try:
-        jsonObject = json.load(open(filePath, 'r'))
-        assert(jsonObject)
-        return jsonObject
-    except Exception as error:
-        raise Exception("Invalid json format or empty json was found in %s - Error: %s" % (filePath, error))
-
-
 def forceRemove(path):
     try:
         shutil.rmtree(path)