python: introduce CAddonPythonInvoker to be used for python scripts run for addons
authormontellese <montellese@xbmc.org>
Wed, 14 Aug 2013 08:02:02 +0000 (10:02 +0200)
committermontellese <montellese@xbmc.org>
Sun, 8 Sep 2013 21:27:33 +0000 (23:27 +0200)
xbmc/interfaces/python/AddonPythonInvoker.cpp [new file with mode: 0644]
xbmc/interfaces/python/AddonPythonInvoker.h [new file with mode: 0644]
xbmc/interfaces/python/Makefile.in
xbmc/interfaces/python/XBPython.cpp
xbmc/interfaces/python/XBPython.h

diff --git a/xbmc/interfaces/python/AddonPythonInvoker.cpp b/xbmc/interfaces/python/AddonPythonInvoker.cpp
new file mode 100644 (file)
index 0000000..d692add
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ *      Copyright (C) 2013 Team XBMC
+ *      http://xbmc.org
+ *
+ *  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 2, 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 XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS)
+  #include "config.h"
+#endif
+
+// python.h should always be included first before any other includes
+#include <Python.h>
+#include <osdefs.h>
+
+#include "system.h"
+#include "AddonPythonInvoker.h"
+#include "addons/AddonVersion.h"
+
+#define MODULE "xbmc"
+
+#define RUNSCRIPT_PRAMBLE \
+        "" \
+        "import " MODULE "\n" \
+        "xbmc.abortRequested = False\n" \
+        "class xbmcout:\n" \
+        "\tdef __init__(self, loglevel=" MODULE ".LOGNOTICE):\n" \
+        "\t\tself.ll=loglevel\n" \
+        "\tdef write(self, data):\n" \
+        "\t\t" MODULE ".log(data,self.ll)\n" \
+        "\tdef close(self):\n" \
+        "\t\t" MODULE ".log('.')\n" \
+        "\tdef flush(self):\n" \
+        "\t\t" MODULE ".log('.')\n" \
+        "import sys\n" \
+        "sys.stdout = xbmcout()\n" \
+        "sys.stderr = xbmcout(" MODULE ".LOGERROR)\n"
+
+#define RUNSCRIPT_OVERRIDE_HACK \
+        "" \
+        "import os\n" \
+        "def getcwd_xbmc():\n" \
+        "  import __main__\n" \
+        "  import warnings\n" \
+        "  if hasattr(__main__, \"__file__\"):\n" \
+        "    warnings.warn(\"os.getcwd() currently lies to you so please use addon.getAddonInfo('path') to find the script's root directory and DO NOT make relative path accesses based on the results of 'os.getcwd.' \", DeprecationWarning, stacklevel=2)\n" \
+        "    return os.path.dirname(__main__.__file__)\n" \
+        "  else:\n" \
+        "    return os.getcwd_original()\n" \
+        "" \
+        "def chdir_xbmc(dir):\n" \
+        "  raise RuntimeError(\"os.chdir not supported in xbmc\")\n" \
+        "" \
+        "os_getcwd_original = os.getcwd\n" \
+        "os.getcwd          = getcwd_xbmc\n" \
+        "os.chdir_orignal   = os.chdir\n" \
+        "os.chdir           = chdir_xbmc\n" \
+        ""
+
+#define RUNSCRIPT_POSTSCRIPT \
+        "print '-->Python Interpreter Initialized<--'\n" \
+        ""
+
+#define RUNSCRIPT_BWCOMPATIBLE \
+  RUNSCRIPT_PRAMBLE RUNSCRIPT_OVERRIDE_HACK RUNSCRIPT_POSTSCRIPT
+
+#define RUNSCRIPT_COMPLIANT \
+  RUNSCRIPT_PRAMBLE RUNSCRIPT_POSTSCRIPT
+
+namespace PythonBindings {
+  void initModule_xbmcgui(void);
+  void initModule_xbmc(void);
+  void initModule_xbmcplugin(void);
+  void initModule_xbmcaddon(void);
+  void initModule_xbmcvfs(void);
+}
+
+using namespace std;
+using namespace PythonBindings;
+
+typedef struct
+{
+  const char *name;
+  CPythonInvoker::PythonModuleInitialization initialization;
+} PythonModule;
+
+static PythonModule PythonModules[] =
+  {
+    { "xbmcgui",    initModule_xbmcgui    },
+    { "xbmc",       initModule_xbmc       },
+    { "xbmcplugin", initModule_xbmcplugin },
+    { "xbmcaddon",  initModule_xbmcaddon  },
+    { "xbmcvfs",    initModule_xbmcvfs    }
+  };
+
+#define PythonModulesSize sizeof(PythonModules) / sizeof(PythonModule)
+
+CAddonPythonInvoker::CAddonPythonInvoker(ILanguageInvocationHandler *invocationHandler)
+  : CPythonInvoker(invocationHandler)
+{ }
+
+CAddonPythonInvoker::~CAddonPythonInvoker()
+{ }
+
+std::map<std::string, CPythonInvoker::PythonModuleInitialization> CAddonPythonInvoker::getModules() const
+{
+  static std::map<std::string, PythonModuleInitialization> modules;
+  if (modules.empty())
+  {
+    for (size_t i = 0; i < PythonModulesSize; i++)
+      modules.insert(make_pair(PythonModules[i].name, PythonModules[i].initialization));
+  }
+
+  return modules;
+}
+
+const char* CAddonPythonInvoker::getInitializationScript() const
+{
+  CStdString addonVer = ADDON::GetXbmcApiVersionDependency(m_addon);
+  bool bwcompatMode = (m_addon.get() == NULL ||
+                       ADDON::AddonVersion(addonVer) <= ADDON::AddonVersion("1.0"));
+  return bwcompatMode ? RUNSCRIPT_BWCOMPATIBLE : RUNSCRIPT_COMPLIANT;
+}
diff --git a/xbmc/interfaces/python/AddonPythonInvoker.h b/xbmc/interfaces/python/AddonPythonInvoker.h
new file mode 100644 (file)
index 0000000..8517981
--- /dev/null
@@ -0,0 +1,34 @@
+#pragma once
+/*
+ *      Copyright (C) 2013 Team XBMC
+ *      http://xbmc.org
+ *
+ *  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 2, 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 XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "interfaces/python/PythonInvoker.h"
+
+class CAddonPythonInvoker : public CPythonInvoker
+{
+public:
+  CAddonPythonInvoker(ILanguageInvocationHandler *invocationHandler);
+  virtual ~CAddonPythonInvoker();
+
+protected:
+  // overrides of CPythonInvoker
+  virtual std::map<std::string, PythonModuleInitialization> getModules() const;
+  virtual const char* getInitializationScript() const;
+};
index 509e8a2..e137ef0 100644 (file)
@@ -11,7 +11,7 @@ all: $(LIB)
 
 include ../../../codegenerator.mk
 
-SRCS=  CallbackHandler.cpp LanguageHook.cpp \
+SRCS=  AddonPythonInvoker.cpp CallbackHandler.cpp LanguageHook.cpp \
        PythonInvoker.cpp XBPython.cpp swig.cpp PyContext.cpp \
        $(GENERATED)
 
index 4a7a94c..281a029 100644 (file)
 
 #include "interfaces/legacy/Monitor.h"
 #include "interfaces/legacy/AddonUtils.h"
+#include "interfaces/python/AddonPythonInvoker.h"
 #include "interfaces/python/PythonInvoker.h"
 
 using namespace ANNOUNCEMENT;
 
-namespace PythonBindings {
-  void initModule_xbmcgui(void);
-  void initModule_xbmc(void);
-  void initModule_xbmcplugin(void);
-  void initModule_xbmcaddon(void);
-  void initModule_xbmcvfs(void);
-}
-
-using namespace PythonBindings;
-
 XBPython::XBPython()
 {
   m_bInitialized      = false;
@@ -419,82 +410,6 @@ void XBPython::UnloadExtensionLibs()
   m_extensions.clear();
 }
 
-#define MODULE "xbmc"
-
-#define RUNSCRIPT_PRAMBLE \
-        "" \
-        "import " MODULE "\n" \
-        "xbmc.abortRequested = False\n" \
-        "class xbmcout:\n" \
-        "\tdef __init__(self, loglevel=" MODULE ".LOGNOTICE):\n" \
-        "\t\tself.ll=loglevel\n" \
-        "\tdef write(self, data):\n" \
-        "\t\t" MODULE ".log(data,self.ll)\n" \
-        "\tdef close(self):\n" \
-        "\t\t" MODULE ".log('.')\n" \
-        "\tdef flush(self):\n" \
-        "\t\t" MODULE ".log('.')\n" \
-        "import sys\n" \
-        "sys.stdout = xbmcout()\n" \
-        "sys.stderr = xbmcout(" MODULE ".LOGERROR)\n"
-
-#define RUNSCRIPT_OVERRIDE_HACK \
-        "" \
-        "import os\n" \
-        "def getcwd_xbmc():\n" \
-        "  import __main__\n" \
-        "  import warnings\n" \
-        "  if hasattr(__main__, \"__file__\"):\n" \
-        "    warnings.warn(\"os.getcwd() currently lies to you so please use addon.getAddonInfo('path') to find the script's root directory and DO NOT make relative path accesses based on the results of 'os.getcwd.' \", DeprecationWarning, stacklevel=2)\n" \
-        "    return os.path.dirname(__main__.__file__)\n" \
-        "  else:\n" \
-        "    return os.getcwd_original()\n" \
-        "" \
-        "def chdir_xbmc(dir):\n" \
-        "  raise RuntimeError(\"os.chdir not supported in xbmc\")\n" \
-        "" \
-        "os_getcwd_original = os.getcwd\n" \
-        "os.getcwd          = getcwd_xbmc\n" \
-        "os.chdir_orignal   = os.chdir\n" \
-        "os.chdir           = chdir_xbmc\n" \
-        ""
-
-#define RUNSCRIPT_POSTSCRIPT \
-        "print '-->Python Interpreter Initialized<--'\n" \
-        ""
-
-#define RUNSCRIPT_BWCOMPATIBLE \
-  RUNSCRIPT_PRAMBLE RUNSCRIPT_OVERRIDE_HACK RUNSCRIPT_POSTSCRIPT
-
-#define RUNSCRIPT_COMPLIANT \
-  RUNSCRIPT_PRAMBLE RUNSCRIPT_POSTSCRIPT
-
-void XBPython::InitializeInterpreter(ADDON::AddonPtr addon)
-{
-  TRACE;
-  {
-    GilSafeSingleLock lock(m_critSection);
-    initModule_xbmcgui();
-    initModule_xbmc();
-    initModule_xbmcplugin();
-    initModule_xbmcaddon();
-    initModule_xbmcvfs();
-  }
-
-  CStdString addonVer = ADDON::GetXbmcApiVersionDependency(addon);
-  bool bwcompatMode = (addon.get() == NULL || (ADDON::AddonVersion(addonVer) <= ADDON::AddonVersion("1.0")));
-  const char* runscript = bwcompatMode ? RUNSCRIPT_BWCOMPATIBLE : RUNSCRIPT_COMPLIANT;
-
-  // redirecting default output to debug console
-  if (PyRun_SimpleString(runscript) == -1)
-    CLog::Log(LOGFATAL, "Python Initialize Error");
-}
-
-void XBPython::DeInitializeInterpreter()
-{
-  TRACE;
-}
-
 /**
 * Should be called before executing a script
 */
@@ -724,7 +639,7 @@ void XBPython::OnScriptEnded(ILanguageInvoker *invoker)
 
 ILanguageInvoker* XBPython::CreateInvoker()
 {
-  return new CPythonInvoker(this);
+  return new CAddonPythonInvoker(this);
 }
 
 void XBPython::PulseGlobalEvent()
index f610bc5..fb73951 100644 (file)
@@ -100,13 +100,6 @@ public:
   void PulseGlobalEvent();
   bool WaitForEvent(CEvent& hEvent, unsigned int milliseconds);
 
-  // inject xbmc stuff into the interpreter.
-  // should be called for every new interpreter
-  void InitializeInterpreter(ADDON::AddonPtr addon);
-
-  // remove modules and references when interpreter done
-  void DeInitializeInterpreter();
-
   void RegisterExtensionLib(LibraryLoader *pLib);
   void UnregisterExtensionLib(LibraryLoader *pLib);
   void UnloadExtensionLibs();