Add a utility to generate python API docs using epydoc

This commit is contained in:
David Sansome 2011-02-15 19:18:53 +00:00
parent fb33ba4cce
commit 0ce8f99494
8 changed files with 173 additions and 54 deletions

View File

@ -308,6 +308,7 @@ add_subdirectory(tests)
add_subdirectory(dist)
add_subdirectory(tools/ultimate_lyrics_parser)
add_subdirectory(scripts)
add_subdirectory(doc/python)
option(WITH_DEBIAN OFF)
if(WITH_DEBIAN)

24
doc/python/CMakeLists.txt Normal file
View File

@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 2.6)
include_directories(${LIBGPOD_INCLUDE_DIRS})
include_directories(${PYTHON_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../src)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../src)
set(SOURCES
generate_python_docs.cpp
)
set(RESOURCES
generate_python_docs.qrc
)
qt4_add_resources(QRC ${RESOURCES})
add_executable(generate_python_docs EXCLUDE_FROM_ALL ${SOURCES} ${QRC})
target_link_libraries(generate_python_docs clementine_lib)
add_custom_target(pythondocs
generate_python_docs
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)

View File

@ -0,0 +1,57 @@
/* This file is part of Clementine.
Copyright 2010, David Sansome <me@davidsansome.com>
Clementine 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.
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Python.h>
#include <QApplication>
#include <QFile>
#include "playlist/playlistitem.h"
#include "scripting/scriptmanager.h"
#include "scripting/python/pythonengine.h"
int main(int argc, char** argv) {
QApplication a(argc, argv);
// Register some meta types required by the exposed classes
qRegisterMetaType<PlaylistItemPtr>("PlaylistItemPtr");
// Create the python engine
ScriptManager manager;
LanguageEngine* language_engine =
manager.EngineForLanguage(ScriptInfo::Language_Python);
PythonEngine* python_engine = qobject_cast<PythonEngine*>(language_engine);
// Initialise python
if (!python_engine->EnsureInitialised()) {
qFatal("Failed to initialise Python engine");
}
// Load the python script
QFile script(":/doc/python/generate_python_docs.py");
script.open(QIODevice::ReadOnly);
QByteArray script_data = script.readAll();
// Run it
PyEval_AcquireLock();
if (PyRun_SimpleString(script_data.constData()) != 0) {
qFatal("Could not execute generate_python_docs.py");
}
PyEval_ReleaseLock();
return 0;
}

View File

@ -0,0 +1,17 @@
import clementine
import epydoc.cli
import sys
sys.argv = [
"epydoc",
"--html",
"-o", "output",
"--introspect-only",
"-v",
"--name", "clementine",
"--url", "http://www.clementine-player.org",
"clementine",
]
print "Running '%s'" % ' '.join(sys.argv)
epydoc.cli.cli()

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/doc/python">
<file>generate_python_docs.py</file>
</qresource>
</RCC>

View File

@ -45,7 +45,12 @@ signals:
void PlaylistFinished();
void VolumeChanged(int volume);
void Error(const QString& message);
void TrackSkipped(PlaylistItemPtr old_track);
// Disabled for now because it causes:
// TypeError: C++ type 'PlaylistItemPtr' is not supported as a native Qt signal type
// void TrackSkipped(PlaylistItemPtr old_track);
void Seeked(qlonglong microseconds);
void ForceShowOSD(Song);

View File

@ -93,73 +93,81 @@ const sipAPIDef* PythonEngine::GetSIPApi() {
#endif
}
Script* PythonEngine::CreateScript(const ScriptInfo& info) {
// Initialise Python if it hasn't been done yet
if (!initialised_) {
AddLogLine("Initialising python...", false);
bool PythonEngine::EnsureInitialised() {
if (initialised_)
return true;
AddLogLine("Initialising python...", false);
#ifdef Q_OS_WIN32
// On Windows we statically link against SIP and PyQt, so add those modules
// to Python's inittab here.
PyImport_AppendInittab(const_cast<char*>("sip"), initsip);
PyImport_AppendInittab(const_cast<char*>("PyQt4.Qt"), initQt);
PyImport_AppendInittab(const_cast<char*>("PyQt4.QtCore"), initQtCore);
PyImport_AppendInittab(const_cast<char*>("PyQt4.QtGui"), initQtGui);
PyImport_AppendInittab(const_cast<char*>("PyQt4.QtNetwork"), initQtNetwork);
// On Windows we statically link against SIP and PyQt, so add those modules
// to Python's inittab here.
PyImport_AppendInittab(const_cast<char*>("sip"), initsip);
PyImport_AppendInittab(const_cast<char*>("PyQt4.Qt"), initQt);
PyImport_AppendInittab(const_cast<char*>("PyQt4.QtCore"), initQtCore);
PyImport_AppendInittab(const_cast<char*>("PyQt4.QtGui"), initQtGui);
PyImport_AppendInittab(const_cast<char*>("PyQt4.QtNetwork"), initQtNetwork);
#endif
// Add the Clementine builtin module
PyImport_AppendInittab(const_cast<char*>("clementine"), initclementine);
// Add the Clementine builtin module
PyImport_AppendInittab(const_cast<char*>("clementine"), initclementine);
// Initialise python
Py_SetProgramName(const_cast<char*>("clementine"));
PyEval_InitThreads();
Py_InitializeEx(0);
// Initialise python
Py_SetProgramName(const_cast<char*>("clementine"));
PyEval_InitThreads();
Py_InitializeEx(0);
// Get the clementine module so we can put stuff in it
clementine_module_ = PyImport_ImportModule("clementine");
if (!clementine_module_) {
AddLogLine("Failed to import the clementine module", true);
if (PyErr_Occurred()) {
PyErr_Print();
}
Py_Finalize();
return NULL;
// Get the clementine module so we can put stuff in it
clementine_module_ = PyImport_ImportModule("clementine");
if (!clementine_module_) {
AddLogLine("Failed to import the clementine module", true);
if (PyErr_Occurred()) {
PyErr_Print();
}
sip_api_ = GetSIPApi();
Py_Finalize();
return false;
}
sip_api_ = GetSIPApi();
// Add objects to the module
if (manager()->data().valid_) {
AddObject(manager()->data().library_->backend(), sipType_LibraryBackend, "library");
AddObject(manager()->data().library_view_, sipType_LibraryView, "library_view");
AddObject(manager()->data().player_, sipType_PlayerInterface, "player");
AddObject(manager()->data().playlists_, sipType_PlaylistManagerInterface, "playlists");
AddObject(manager()->data().radio_model_, sipType_RadioModel, "radio_model");
AddObject(manager()->data().settings_dialog_, sipType_SettingsDialog, "settings_dialog");
AddObject(manager()->data().task_manager_, sipType_TaskManager, "task_manager");
}
// Add objects to the module
if (manager()->data().valid_) {
AddObject(manager()->data().library_->backend(), sipType_LibraryBackend, "library");
AddObject(manager()->data().library_view_, sipType_LibraryView, "library_view");
AddObject(manager()->data().player_, sipType_PlayerInterface, "player");
AddObject(manager()->data().playlists_, sipType_PlaylistManagerInterface, "playlists");
AddObject(manager()->data().radio_model_, sipType_RadioModel, "radio_model");
AddObject(manager()->data().settings_dialog_, sipType_SettingsDialog, "settings_dialog");
AddObject(manager()->data().task_manager_, sipType_TaskManager, "task_manager");
}
AddObject(manager()->ui(), sipType_UIInterface, "ui");
AddObject(this, sipType_PythonEngine, "pythonengine");
AddObject(manager()->ui(), sipType_UIInterface, "ui");
AddObject(this, sipType_PythonEngine, "pythonengine");
// Create a module for scripts
PyImport_AddModule(kModulePrefix);
// Create a module for scripts
PyImport_AddModule(kModulePrefix);
// Run the startup script - this redirects sys.stdout and sys.stderr to our
// log handler.
QFile python_startup(":pythonstartup.py");
python_startup.open(QIODevice::ReadOnly);
QByteArray python_startup_script = python_startup.readAll();
// Run the startup script - this redirects sys.stdout and sys.stderr to our
// log handler.
QFile python_startup(":pythonstartup.py");
python_startup.open(QIODevice::ReadOnly);
QByteArray python_startup_script = python_startup.readAll();
if (PyRun_SimpleString(python_startup_script.constData()) != 0) {
AddLogLine("Could not execute startup code", true);
Py_Finalize();
return NULL;
}
if (PyRun_SimpleString(python_startup_script.constData()) != 0) {
AddLogLine("Could not execute startup code", true);
Py_Finalize();
return false;
}
PyEval_ReleaseLock();
PyEval_ReleaseLock();
initialised_ = true;
initialised_ = true;
return true;
}
Script* PythonEngine::CreateScript(const ScriptInfo& info) {
// Initialise Python if it hasn't been done yet
if (!EnsureInitialised()) {
return NULL;
}
Script* ret = new PythonScript(this, info);

View File

@ -38,6 +38,8 @@ public:
ScriptInfo::Language language() const { return ScriptInfo::Language_Python; }
QString name() const { return "python"; }
bool EnsureInitialised();
Script* CreateScript(const ScriptInfo& info);
void DestroyScript(Script* script);