diff --git a/qt/python/mantidqt/widgets/codeeditor.py b/qt/python/mantidqt/widgets/codeeditor.py
new file mode 100644
index 0000000000000000000000000000000000000000..988c2d207f1d3a4c695ea3003a345f43c9ed9118
--- /dev/null
+++ b/qt/python/mantidqt/widgets/codeeditor.py
@@ -0,0 +1,22 @@
+#  This file is part of the mantidqt package
+#
+#  Copyright (C) 2017 mantidproject
+#
+#  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/>.
+from __future__ import (absolute_import)
+
+from mantidqt.utils.qt import import_qtlib
+
+
+CodeEditor = import_qtlib('_widgetscore', 'mantidqt.widgets', 'ScriptEditor')
diff --git a/qt/python/mantidqt/widgets/src/_widgetscore.sip b/qt/python/mantidqt/widgets/src/_widgetscore.sip
index fd62bf8e44a043fbc067983795b63d07cc89a583..72d08195d57fc4c5eb3e76dd839f517f2efaef32 100644
--- a/qt/python/mantidqt/widgets/src/_widgetscore.sip
+++ b/qt/python/mantidqt/widgets/src/_widgetscore.sip
@@ -8,6 +8,24 @@ using namespace MantidQt::MantidWidgets;
 qRegisterMetaType<MantidQt::MantidWidgets::Message>();
 %End
 
+// ----------------------------------------------------------------------------
+// Exceptions
+// ----------------------------------------------------------------------------
+
+%Exception std::invalid_argument(SIP_Exception) /PyName=ValueError/
+{
+%TypeHeaderCode
+#include <stdexcept>
+%End
+%RaiseCode
+    const char *detail = sipExceptionRef.what();
+
+    SIP_BLOCK_THREADS
+    PyErr_SetString(PyExc_ValueError, detail);
+    SIP_UNBLOCK_THREADS
+%End
+};
+
 // ----------------------------------------------------------------------------
 // Classes
 // ----------------------------------------------------------------------------
@@ -36,3 +54,15 @@ public:
   MessageDisplay(QWidget *parent = 0);
   void attachLoggingChannel();
 };
+
+class ScriptEditor {
+%TypeHeaderCode
+#include "MantidQtWidgets/Common/ScriptEditor.h"
+%End
+
+public:
+  ScriptEditor(const QString & language,
+               QWidget *parent /TransferThis/ = 0) throw(std::invalid_argument);
+private:
+  ScriptEditor(const ScriptEditor&);
+};
diff --git a/qt/python/mantidqt/widgets/test/test_codeeditor.py b/qt/python/mantidqt/widgets/test/test_codeeditor.py
new file mode 100644
index 0000000000000000000000000000000000000000..c12563344389786ff44f26553cd18420fcf62ac7
--- /dev/null
+++ b/qt/python/mantidqt/widgets/test/test_codeeditor.py
@@ -0,0 +1,50 @@
+#    This file is part of the mantid workbench.
+#
+#    Copyright (C) 2017 mantidproject
+#
+#    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/>.
+from __future__ import (absolute_import, unicode_literals)
+
+# system imports
+import unittest
+
+# third-party library imports
+
+# local imports
+from mantidqt.widgets.codeeditor import CodeEditor
+from mantidqt.utils.qt.testing import requires_qapp
+
+
+@requires_qapp
+class CodeEditorTest(unittest.TestCase):
+
+    # Success tests
+
+    def test_construction_accepts_Python_as_language(self):
+        widget = CodeEditor("Python")
+
+    # Failure tests
+
+    def test_construction_raises_error_for_unknown_language(self):
+        # self.assertRaises causes a segfault here for some reason...
+        try:
+            CodeEditor("MyCoolLanguage")
+        except ValueError:
+            pass
+        except Exception as exc:
+            self.fail("Expected a Value error to be raised but found a " + exc.__name__)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/qt/widgets/common/src/ScriptEditor.cpp b/qt/widgets/common/src/ScriptEditor.cpp
index 65cdc94f84753afc190fa18dd2010f0f5157749e..4e0d52ca40e27c56b7b5a3ecec980b04fe57d0bf 100644
--- a/qt/widgets/common/src/ScriptEditor.cpp
+++ b/qt/widgets/common/src/ScriptEditor.cpp
@@ -37,15 +37,13 @@ namespace {
  * Return a new instance of a lexer based on the given language
  * @param language A string defining the language. Currently hardcoded to
  * Python.
- * @param editor The editor that the lexer will be installed on.
  * @return A new QsciLexer instance
  */
-QsciLexer *createLexerFromLanguage(const QString &language,
-                                   QsciScintilla *editor) {
+QsciLexer *createLexerFromLanguage(const QString &language) {
   if (language != "Python")
     throw std::invalid_argument("createLexerFromLanguage: Unsupported "
                                 "language. Supported languages=Python");
-  return new QsciLexerPython(editor);
+  return new QsciLexerPython;
 }
 }
 
@@ -64,7 +62,7 @@ QColor ScriptEditor::g_error_colour = QColor("red");
  * @param parent Parent widget
  */
 ScriptEditor::ScriptEditor(const QString &language, QWidget *parent)
-    : ScriptEditor(parent, createLexerFromLanguage(language, this)) {}
+    : ScriptEditor(parent, createLexerFromLanguage(language)) {}
 
 /**
  * Constructor