Add a Hello World Python script example to the docs
This commit is contained in:
parent
6d8c87418a
commit
d7fb89fa33
@ -24,6 +24,16 @@ configure_file(
|
|||||||
COPYONLY
|
COPYONLY
|
||||||
)
|
)
|
||||||
|
|
||||||
|
file(GLOB EPYDOC_PAGES ${CMAKE_CURRENT_SOURCE_DIR}/*.epydoc)
|
||||||
|
foreach(file ${EPYDOC_PAGES})
|
||||||
|
get_filename_component(filename ${file} NAME)
|
||||||
|
configure_file(
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/${filename}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/${filename}
|
||||||
|
COPYONLY
|
||||||
|
)
|
||||||
|
endforeach(file)
|
||||||
|
|
||||||
add_custom_target(pythondocs
|
add_custom_target(pythondocs
|
||||||
generate_python_docs
|
generate_python_docs
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
102
doc/python/doc-hello-world.epydoc
Normal file
102
doc/python/doc-hello-world.epydoc
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
Hello world!
|
||||||
|
============
|
||||||
|
|
||||||
|
Clementine allows users to load scripts written in Python. These scripts run
|
||||||
|
in a Python interpreter inside Clementine itself and have access to
|
||||||
|
Clementine's internals through a special L{clementine} module. Scripts can
|
||||||
|
create graphical user interfaces using the Python Qt bindings.
|
||||||
|
|
||||||
|
Let's begin by creating a script that shows a dialog box when loaded.
|
||||||
|
|
||||||
|
Creating a simple script
|
||||||
|
========================
|
||||||
|
|
||||||
|
Create a directory called C{helloworld}. All files for this script will live
|
||||||
|
in this directory.
|
||||||
|
|
||||||
|
Inside the C{helloworld} directory create a file called C{main.py}. This will
|
||||||
|
contain all the Python source code for this script.
|
||||||
|
|
||||||
|
>>> from PyQt4.QtGui import QMessageBox
|
||||||
|
...
|
||||||
|
... QMessageBox.information(None, "Hello world!", "My script was loaded!")
|
||||||
|
|
||||||
|
B{Note:} It is possible (and recommended) to split large scripts up into multiple
|
||||||
|
classes stored in separate files, and C{import} them as in a normal Python
|
||||||
|
application. For now we will put all the code into a single file.
|
||||||
|
|
||||||
|
This code imports the C{PyQt4.QtGui.QMessageBox} class from the Python Qt
|
||||||
|
bindings and displays a simple information message box when the script is
|
||||||
|
loaded.
|
||||||
|
|
||||||
|
The script.ini
|
||||||
|
==============
|
||||||
|
|
||||||
|
You now have some Python source code in a directory, but Clementine won't
|
||||||
|
recognise it as being a loadable script. You need to create a C{script.ini}
|
||||||
|
file with some information about your script:
|
||||||
|
|
||||||
|
>>> [Script]
|
||||||
|
... name=Hello world!
|
||||||
|
... description=My first script
|
||||||
|
... author=Fred <fred@example.com>
|
||||||
|
... url=http://www.example.com
|
||||||
|
... icon=:/icon.png
|
||||||
|
...
|
||||||
|
... language=python
|
||||||
|
... script_file=main.py
|
||||||
|
|
||||||
|
Let's look at what each of these fields is for:
|
||||||
|
|
||||||
|
- B{name} - The short name of your script that is displayed to the user in
|
||||||
|
bold in the Script Manager dialog.
|
||||||
|
- B{description} - A longer description of your script. Try to explain
|
||||||
|
briefly what the script does and what the user should do to start using it.
|
||||||
|
- B{author} I{[optional]} - Your name and email address in the format
|
||||||
|
C{Name <email@address>}. This is not currently used, but may be in the
|
||||||
|
future.
|
||||||
|
- B{url} I{[optional]} - A URL of this script's homepage. This is not
|
||||||
|
currently used, but may be in the future.
|
||||||
|
- B{icon} - The filename (relative to the script's directory) of an icon to
|
||||||
|
display next to the script in the Script Manager dialog. You can put an
|
||||||
|
image (.png or .jpg) into the C{helloworld} directory and refer to that
|
||||||
|
here. The image should be at least 64x64 pixels big. Notice in this
|
||||||
|
example we use a filename starting with C{:/}. This is a Qt resource path,
|
||||||
|
and refers to one of the icons embedded within Clementine.
|
||||||
|
- B{language} - The language the script is written in. Currently this must
|
||||||
|
be set to C{python}, but more languages may be supported in the future.
|
||||||
|
- B{script_file} - The Python source file to load for this script. If your
|
||||||
|
script consists of multiple files then the one specified here is the main
|
||||||
|
one that will be loaded first.
|
||||||
|
|
||||||
|
Adding the script to Clementine
|
||||||
|
===============================
|
||||||
|
|
||||||
|
Clementine searches for its scripts in a couple of different places depending
|
||||||
|
on the operating system:
|
||||||
|
|
||||||
|
B{On Windows:}
|
||||||
|
|
||||||
|
- C{%UserProfile%\.config\Clementine\scripts} (where C{%UserProfile%} might be
|
||||||
|
C{C:\Users\YourUsername} on Windows Vista or Windows 7, or
|
||||||
|
C{C:\Documents and Settings\YourUsername} on XP).
|
||||||
|
- C{C:\Program Files\Clementine\scripts}
|
||||||
|
|
||||||
|
B{On Linux:}
|
||||||
|
|
||||||
|
- C{~/.config/Clementine/scripts}
|
||||||
|
- C{/usr/share/clementine/scripts}
|
||||||
|
- C{/usr/local/share/clementine/scripts}
|
||||||
|
- C{$PREFIX/share/clementine/scripts} (if Clementine was installed into a
|
||||||
|
different prefix).
|
||||||
|
|
||||||
|
B{On Mac OS X:}
|
||||||
|
|
||||||
|
- C{~/Library/Application Support/Clementine/scripts}
|
||||||
|
|
||||||
|
For development you should copy your C{helloworld} directory (or create a
|
||||||
|
symbolic link) into one of these locations. Clementine should notice the new
|
||||||
|
script straight away and add it to the Script Manager dialog.
|
||||||
|
|
||||||
|
Load your script by clicking on it in the Script Manager dialog and clicking
|
||||||
|
the C{Enable} button.
|
@ -34,7 +34,7 @@ h2 { font-size: +125%;
|
|||||||
font-weight: bold; }
|
font-weight: bold; }
|
||||||
h3 { font-size: +110%; font-style: italic;
|
h3 { font-size: +110%; font-style: italic;
|
||||||
font-weight: normal; }
|
font-weight: normal; }
|
||||||
code { font-size: 100%; font-family: monospace;
|
code { font-family: monospace;
|
||||||
color: #007000; }
|
color: #007000; }
|
||||||
hr { height: 1px; background-color: #BBB; border: 0px; }
|
hr { height: 1px; background-color: #BBB; border: 0px; }
|
||||||
/* N.B.: class, not pseudoclass */
|
/* N.B.: class, not pseudoclass */
|
||||||
@ -76,8 +76,9 @@ div.sidebar {
|
|||||||
left: 0px;
|
left: 0px;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
width: 350px;
|
width: 350px;
|
||||||
margin-left: 6px;
|
padding-left: 6px;
|
||||||
margin-right: 6px;
|
padding-right: 6px;
|
||||||
|
border-right: 3px solid #E5ECF9;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.maincontent {
|
div.maincontent {
|
||||||
@ -286,8 +287,8 @@ div.py-highlight-hdr { border-top: 2px solid #000000;
|
|||||||
background: #d8e8e8; }
|
background: #d8e8e8; }
|
||||||
div.py-highlight { border-bottom: 2px solid #000000;
|
div.py-highlight { border-bottom: 2px solid #000000;
|
||||||
background: #d0e0e0; }
|
background: #d0e0e0; }
|
||||||
.py-prompt { color: #005050; font-weight: bold;}
|
.py-prompt { color: #005050; font-weight: bold; display: none; }
|
||||||
.py-more { color: #005050; font-weight: bold;}
|
.py-more { color: #005050; font-weight: bold; display: none; }
|
||||||
.py-string { color: #006030; }
|
.py-string { color: #006030; }
|
||||||
.py-comment { color: #003060; }
|
.py-comment { color: #003060; }
|
||||||
.py-keyword { color: #600000; }
|
.py-keyword { color: #600000; }
|
||||||
|
@ -1,12 +1,22 @@
|
|||||||
|
import epydoc
|
||||||
import epydoc.apidoc
|
import epydoc.apidoc
|
||||||
import epydoc.cli
|
import epydoc.cli
|
||||||
|
import epydoc.docbuilder
|
||||||
import epydoc.docintrospecter
|
import epydoc.docintrospecter
|
||||||
import epydoc.docwriter.html
|
import epydoc.docwriter.html
|
||||||
|
import epydoc.markup.epytext
|
||||||
import inspect
|
import inspect
|
||||||
import PyQt4.QtCore
|
import PyQt4.QtCore
|
||||||
import sys
|
import sys
|
||||||
import types
|
import types
|
||||||
|
|
||||||
|
DOC_PAGES = [
|
||||||
|
("Hello world!", "doc-hello-world"),
|
||||||
|
]
|
||||||
|
|
||||||
|
OUTPUT_DIR = "output"
|
||||||
|
|
||||||
|
|
||||||
# SIP does some strange stuff with the __dict__ of wrapped C++ classes:
|
# SIP does some strange stuff with the __dict__ of wrapped C++ classes:
|
||||||
# someclass.__dict__["function"] != someclass.function
|
# someclass.__dict__["function"] != someclass.function
|
||||||
# These little hacks make epydoc generate documentation for the actual functions
|
# These little hacks make epydoc generate documentation for the actual functions
|
||||||
@ -43,21 +53,27 @@ def my_write_header(self, out, title):
|
|||||||
|
|
||||||
out('<div class="sidebar">')
|
out('<div class="sidebar">')
|
||||||
|
|
||||||
self.write_toc_section(out, "All Classes", self.class_list)
|
# General doc pages
|
||||||
|
out('<h2 class="toc">%s</h2>\n' % "Documentation")
|
||||||
|
for (title, filename) in DOC_PAGES:
|
||||||
|
out('<a href="%s.html">%s</a><br/>' % (filename, title))
|
||||||
|
|
||||||
# List the functions.
|
# Classes
|
||||||
|
self.write_toc_section(out, "Class reference", self.class_list)
|
||||||
|
|
||||||
|
# Functions
|
||||||
funcs = [d for d in self.routine_list
|
funcs = [d for d in self.routine_list
|
||||||
if not isinstance(self.docindex.container(d),
|
if not isinstance(self.docindex.container(d),
|
||||||
(epydoc.apidoc.ClassDoc, types.NoneType))]
|
(epydoc.apidoc.ClassDoc, types.NoneType))]
|
||||||
self.write_toc_section(out, "All Functions", funcs)
|
self.write_toc_section(out, "Function reference", funcs)
|
||||||
|
|
||||||
# List the variables.
|
# Variables
|
||||||
vars = []
|
vars = []
|
||||||
for doc in self.module_list:
|
for doc in self.module_list:
|
||||||
vars += doc.select_variables(value_type='other',
|
vars += doc.select_variables(value_type='other',
|
||||||
imported=False,
|
imported=False,
|
||||||
public=self._public_filter)
|
public=self._public_filter)
|
||||||
self.write_toc_section(out, "All Variables", vars)
|
self.write_toc_section(out, "Variable reference", vars)
|
||||||
|
|
||||||
out('</div>')
|
out('</div>')
|
||||||
out('<div class="maincontent">')
|
out('<div class="maincontent">')
|
||||||
@ -82,7 +98,7 @@ epydoc.docwriter.html.HTMLWriter.write_toc_section = my_write_toc_section
|
|||||||
sys.argv = [
|
sys.argv = [
|
||||||
"epydoc",
|
"epydoc",
|
||||||
"--html",
|
"--html",
|
||||||
"-o", "output",
|
"-o", OUTPUT_DIR,
|
||||||
"-v",
|
"-v",
|
||||||
"--name", "clementine",
|
"--name", "clementine",
|
||||||
"--url", "http://www.clementine-player.org",
|
"--url", "http://www.clementine-player.org",
|
||||||
@ -94,4 +110,29 @@ sys.argv = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
print "Running '%s'" % ' '.join(sys.argv)
|
print "Running '%s'" % ' '.join(sys.argv)
|
||||||
epydoc.cli.cli()
|
|
||||||
|
# Parse arguments
|
||||||
|
(options, names) = epydoc.cli.parse_arguments()
|
||||||
|
|
||||||
|
# Write the main docs - this is copied from cli()
|
||||||
|
epydoc.docstringparser.DEFAULT_DOCFORMAT = options.docformat
|
||||||
|
docindex = epydoc.docbuilder.build_doc_index(names,
|
||||||
|
options.introspect, options.parse,
|
||||||
|
add_submodules=True)
|
||||||
|
html_writer = epydoc.docwriter.html.HTMLWriter(docindex, **options.__dict__)
|
||||||
|
html_writer.write(options.target)
|
||||||
|
|
||||||
|
# Write extra pages
|
||||||
|
def write_extra_page(out, title, source):
|
||||||
|
handle = open(source, 'r')
|
||||||
|
parsed_docstring = epydoc.markup.epytext.parse_docstring(handle.read(), [])
|
||||||
|
html_writer.write_header(out, title)
|
||||||
|
out(html_writer.docstring_to_html(parsed_docstring))
|
||||||
|
html_writer.write_footer(out)
|
||||||
|
|
||||||
|
for (title, filename) in DOC_PAGES:
|
||||||
|
source = "%s.epydoc" % filename
|
||||||
|
html = "%s.html" % filename
|
||||||
|
print "Generating '%s' from '%s'..." % (html, source)
|
||||||
|
|
||||||
|
html_writer._write(write_extra_page, OUTPUT_DIR, html, title, source)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user