diff --git a/docs/sphinx/_static/images/sphinxdocs/user.png b/docs/sphinx/_static/images/sphinxdocs/user.png new file mode 100644 index 00000000..749c825e Binary files /dev/null and b/docs/sphinx/_static/images/sphinxdocs/user.png differ diff --git a/docs/sphinx/_static/images/widgets/fullsize/wxgtk/genericdirctrl.png b/docs/sphinx/_static/images/widgets/fullsize/wxgtk/genericdirctrl.png new file mode 100644 index 00000000..0ddd0329 Binary files /dev/null and b/docs/sphinx/_static/images/widgets/fullsize/wxgtk/genericdirctrl.png differ diff --git a/docs/sphinx/_static/images/widgets/fullsize/wxgtk/treectrl.png b/docs/sphinx/_static/images/widgets/fullsize/wxgtk/treectrl.png new file mode 100644 index 00000000..797381d2 Binary files /dev/null and b/docs/sphinx/_static/images/widgets/fullsize/wxgtk/treectrl.png differ diff --git a/docs/sphinx/_static/images/widgets/fullsize/wxmac/genericdirctrl.png b/docs/sphinx/_static/images/widgets/fullsize/wxmac/genericdirctrl.png new file mode 100644 index 00000000..0c65af47 Binary files /dev/null and b/docs/sphinx/_static/images/widgets/fullsize/wxmac/genericdirctrl.png differ diff --git a/docs/sphinx/_static/images/widgets/fullsize/wxmac/treectrl.png b/docs/sphinx/_static/images/widgets/fullsize/wxmac/treectrl.png new file mode 100644 index 00000000..190c6234 Binary files /dev/null and b/docs/sphinx/_static/images/widgets/fullsize/wxmac/treectrl.png differ diff --git a/docs/sphinx/_static/images/widgets/fullsize/wxmsw/genericdirctrl.png b/docs/sphinx/_static/images/widgets/fullsize/wxmsw/genericdirctrl.png new file mode 100644 index 00000000..0dd9a21e Binary files /dev/null and b/docs/sphinx/_static/images/widgets/fullsize/wxmsw/genericdirctrl.png differ diff --git a/docs/sphinx/_static/images/widgets/fullsize/wxmsw/treectrl.png b/docs/sphinx/_static/images/widgets/fullsize/wxmsw/treectrl.png new file mode 100644 index 00000000..db1b7ed5 Binary files /dev/null and b/docs/sphinx/_static/images/widgets/fullsize/wxmsw/treectrl.png differ diff --git a/docs/sphinx/_templates/main.html b/docs/sphinx/_templates/main.html index 073961c5..c0f76ff0 100644 --- a/docs/sphinx/_templates/main.html +++ b/docs/sphinx/_templates/main.html @@ -49,6 +49,17 @@ shows the main thoughts behind the project Phoenix implementation +
+ +
+

Note

+ + If you wish to help in the documentation effort, the main docstrings guidelines are outlined in + this document. +
+ +
+

The Phoenix documentation has been built automatically starting from XML files representing the wxWidgets C++ documentation (generated using Doxygen). diff --git a/docs/sphinx/conf.py b/docs/sphinx/conf.py index d3309f1b..5af9a344 100644 --- a/docs/sphinx/conf.py +++ b/docs/sphinx/conf.py @@ -56,7 +56,7 @@ copyright = u'2012, Andrea Gavana' # The short X.Y version. version = '2.9' # The full version, including alpha/beta/rc tags. -release = '2.9.3.74 (Phoenix)' +release = '2.9.4.80 (Phoenix)' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -158,7 +158,7 @@ html_use_index = True html_split_index = True # If true, links to the reST sources are added to the pages. -html_show_sourcelink = False +html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True diff --git a/docs/sphinx/rest_substitutions/overviews/DocstringsGuidelines.rst b/docs/sphinx/rest_substitutions/overviews/DocstringsGuidelines.rst new file mode 100644 index 00000000..4001985d --- /dev/null +++ b/docs/sphinx/rest_substitutions/overviews/DocstringsGuidelines.rst @@ -0,0 +1,271 @@ +.. include:: headings.inc + +.. highlight:: rst + + +.. _docstrings guidelines: + +================================================== +|phoenix_title| **Phoenix Docstrings Guidelines** +================================================== + +This document gives a brief introduction about the current docstrings standards +in the Phoenix project. Most of the documentation in the Phoenix core is automatically +generated by parsing the wxWidgets XML docs; however, Phoenix has its own pure-Python +functions and classes in at least two places: + +* **Core Library**: examples include :ref:`CallLater` and :func:`date2pydate`, which require + manual input od the documentation strings. This is achieved by editing the source Python files + located in the ``etg`` folder in the Phoenix directory tree; +* **wx.lib**: the whole of ``wx.lib`` (and its sub-folders) is made up of pure-Python modules, + ofter representing owner-drawn widgets which are not available as wrapped modules. Again, + this requires manual editing of the source Python files. + +This document is a starting point in setting some reasonable standards on how the pure-Python +docstrings may be edited and improved to make the overall appearance of the Phoenix documentation +consistent and pleasant. + + +.. _info field lists: + +Info Field Lists +---------------- + +`Info Field Lists` refer to the various options available while documenting a method or a function, +and in particular its parameters, keywords, return type and possibly raised Python `Exceptions`. + +Inside Python object description directives, reST field lists with these fields +are recognized and formatted nicely: + +* ``param``, ``parameter``, ``arg``, ``argument``, ``key``, ``keyword``: + Description of a parameter. +* ``type``: Type of a parameter. +* ``raises``, ``raise``, ``except``, ``exception``: That (and when) a specific + exception is raised. +* ``var``, ``ivar``, ``cvar``: Description of a variable. +* ``returns``, ``return``: Description of the return value. +* ``rtype``: Return type. + + +The field names must consist of one of these keywords and an argument (except +for ``returns`` and ``rtype``, which do not need an argument). This is best +explained by an example:: + + .. method:: Set3StateValue(self, state): + + Sets the checkbox item to the given `state`. + + :param `state`: can be one of: ``wx.CHK_UNCHECKED`` (check is off), ``wx.CHK_CHECKED`` + (check is on) or ``wx.CHK_UNDETERMINED`` (check is mixed). + :type `state`: integer + + :returns: ``True`` if the value was successfully set, ``False`` otherwise. + :rtype: bool + + :raise: `Exception` when the item is not a 3-state checkbox item. + +| + +This will render like this: + + .. method:: Set3StateValue(self, state): + :noindex: + + Sets the checkbox item to the given `state`. + + :param `state`: can be one of: ``wx.CHK_UNCHECKED`` (check is off), ``wx.CHK_CHECKED`` + (check is on) or ``wx.CHK_UNDETERMINED`` (check is mixed). + :type `state`: integer + + :returns: ``True`` if the value was successfully set, ``False`` otherwise. + :rtype: bool + + :raise: `Exception` when the item is not a 3-state checkbox item. + + +| + +It is also possible to combine parameter type and description, if the type is a +single word, like this:: + + :param integer `state`: can be one of: ``wx.CHK_UNCHECKED`` (check is off), ``wx.CHK_CHECKED`` + (check is on) or ``wx.CHK_UNDETERMINED`` (check is mixed). + + +In general, the standards for the ``:param`` field are the following: + +1. Do not use the ``@param`` construct, as I am not sure Sphinx and docutils understand it; +2. Always try and define the parameter type: if the parameter is another Phoenix class, you can simply + write this:: + + :param Point `pt`: the mouse pointer location. + + Or, alternatively:: + + :param `pt`: the mouse pointer location. + :type `pt`: `Point` + + +Similarly, for the ``:return:`` and ``:rtype:`` field, you may consider doing the following: + +1. Try and put double-backticks on words like ``True``, ``False``, ``None`` and the various + Phoenix constants (i.e., ``wx.TR_DEFAULT_STYLE``); +2. If you can't guess what a method function returns, just leave the ``:returns:`` and ``:rtype:`` + fields blank. + + +.. seealso:: `Sphinx Info Field List `_ + + +.. _admonitions: + +Admonitions +----------- + +Admonitions are specially marked "topics" that can appear anywhere an ordinary body element can. +They contain arbitrary body elements. Typically, an admonition is rendered as an offset block +in a document, sometimes outlined or shaded, with a title matching the admonition type. For example:: + + .. warning:: I am a warning. + + +Will render as: + +.. warning:: I am a warning. + +| + +Currently, the `sphinx_generator` tool recognizes the following admonitions: + +1. ``.. note::`` : simple annotations to make a particular comment/sentence + stand out against the rest of the documentation strings for a particular class, method or function; +2. ``.. warning::`` : this admonition normally indicates a problem or a severe limitation of a method, + class or function. In the Phoenix world, this may also indicate that a particular widget is not + supported under one or more platforms; +3. ``.. deprecated::`` : used to mark deprecated methods, classes or functions; +4. ``.. availability::`` : normally employed to make the user understand on which platform(s) a particular + functionality is supported/available; +5. ``.. seealso::`` : added primarily to facilitate the browsing of the docs, this admonition + should be employed every time you think a user may be interested in seeing a related/similar method + or a function providing an alternative implementation; +6. ``.. todo::`` : used to mark incomplete methods/functions, or simply as a remainder for the user and + the developer that some more functionality needs to be added. + +You can put pretty much anything inside an admonition section, as long as it is properly indented. The +recommendation is to implement it like this:: + + .. note:: + + The class :ref:`TreeCtrl` can be used to display a tree, with these notes: + + - The note contains all indented body elements + following. + - It includes this bullet list. + + +| + +Which will render as follows: + +.. note:: + + The class :ref:`TreeCtrl` can be used to display a tree, with these notes: + + - The note contains all indented body elements + following. + - It includes this bullet list. + + + +In addition to the aforementioned admonitions, you can also use the default Sphinx directives +like ``.. versionadded::`` and ``.. versionchanged::``, to highlight the fact that some method, +function or class has been added/modified starting with a particular Phoenix version. + + +.. seealso:: `Sphinx Paragraph-level markup `_ + + +.. _contributing samples: + +Contributing Samples +-------------------- + +.. highlight:: python + +If you wish to contribute a (short) sample to be included in the documentation, please follow +these conventions: + +1. Name the snippet of code like ``classname.methodname.INTEGER.py``, i.e. if you wish to contribute 2 + snippets about the :meth:`CheckBox.SetValue` method, please name your snippet files like this: + + * `CheckBox.SetValue.1.py` + * `CheckBox.SetValue.2.py` + + +2. At the very top of the snippet file (on the first line), put your name, or your alias, or anything + you use as internet name preceeded by a double-hash, i.e.: + + ``##Andrea Gavana`` + + + So that your source code looks more or less like this:: + + ##Chris Barker + #!/usr/bin/env python + + """ + A simple test of the GridBagSizer + http://wiki.wxpython.org/index.cgi/WriteItYourself + """ + + # Whatever code here... + def SendSizeEvent(self): + + self.AdjustMySize() + + + +.. highlight:: rst + +This snippet will end up in the snippets `contrib` folder, to differentiate it from the snippets +automatically generated when parsing the wxWidgets C++ XML documentation. + +Please keep the snippets as short as possible: they don't need to be fully-runnable and self contained +applications, they are simply meant to show a particular/clever/unusual way of using a method, a class +or a function. + +Please do send your sample snippets to me at `this `_ e-mail address or, if +you have commit rights in the current Phoenix SVN area, feel free to upload them yourself under the +following folder: + +``/trunk/docs/sphinx/rest_substitutions/snippets/python/contrib`` + + +.. _contributing screenshots: + +Contributing Screenshots +------------------------ + +Currently Phoenix is relatively short of widgets screenshots, especially on Linux/Mac platforms. + +If you wish to contribute a screenshot of a widget to be included in the documentation, please follow +these conventions: + +- If the widget is a class belonging to the main `wx` namespace, just use the + class name in lower case (i.e., `wx.Frame` ==> `frame.png`); +- If it belongs to a sub-namespace (i.e., `wx.dataview`, `wx.aui`, `wx.html` + and so on), it should be named this way (examples): + + 1) `wx.dataview.DataViewCtrl` ==> `dataview.dataviewctrl.png` + 2) `wx.aui.AuiManager` ==> `aui.auimanager.png` + + +Please do send your screenshots to me at `this `_ e-mail address or, if +you have commit rights in the current Phoenix SVN area, feel free to upload them yourself under the +following folder: + +``/trunk/docs/sphinx/_static/images/widgets/fullsize`` + +Please make sure to upload your images in the appropriate sub-folder, depending on the platform you +chose to take the screenshots on. + diff --git a/docs/sphinx/rest_substitutions/overviews/index.rst b/docs/sphinx/rest_substitutions/overviews/index.rst index ca412d72..767da949 100644 --- a/docs/sphinx/rest_substitutions/overviews/index.rst +++ b/docs/sphinx/rest_substitutions/overviews/index.rst @@ -126,7 +126,7 @@ project in the `wxWidgets SVN `_. wxPython Documentation ---------------------- -The new wxPython API documentation is available `in this page `_. +The new wxPython API documentation is available `in this page `_. .. toctree:: diff --git a/docs/sphinx/rest_substitutions/overviews/treectrl_overview.rst b/docs/sphinx/rest_substitutions/overviews/treectrl_overview.rst new file mode 100644 index 00000000..9da7656f --- /dev/null +++ b/docs/sphinx/rest_substitutions/overviews/treectrl_overview.rst @@ -0,0 +1,69 @@ +.. include:: headings.inc + + +.. _treectrl overview: + +=============================================== +|phoenix_title| **TreeCtrl Overview** +=============================================== + +The tree control displays its items in a tree like structure. Each item has its own (optional) icon +and a label. An item may be either collapsed (meaning that its children are not visible) or expanded +(meaning that its children are shown). Each item in the tree is identified by its itemId which is of +opaque data type :ref:`TreeItemId`. You can test whether an item is valid by calling :meth:`TreeItemId.IsOk`. + +The items text and image may be retrieved and changed with `(Get|Set)ItemText` and `(Get|Set)ItemImage`. +In fact, an item may even have two images associated with it: the normal one and another one for selected +state which is set/retrieved with `(Get|Set)ItemSelectedImage` functions, but this functionality might +be unavailable on some platforms. + +Tree items have several attributes: an item may be selected or not, visible or not, bold or not. It may +also be expanded or collapsed. All these attributes may be retrieved with the corresponding functions: +:meth:`TreeCtrl.IsSelected`, :meth:`TreeCtrl.IsVisible`, :meth:`TreeCtrl.IsBold` and :meth:`TreeCtrl.IsExpanded`. +Only one item at a time may be selected, selecting another one (with :meth:`TreeCtrl.SelectItem`) automatically +unselects the previously selected one. + +In addition to its icon and label, a user-specific data structure may be associated with all tree items. +If you wish to do it, you should derive a class from :ref:`TreeItemData` which is a very simple class +having only one function `GetId()` which returns the id of the item this data is associated with. This data +will be freed by the control itself when the associated item is deleted (all items are deleted when the +control is destroyed), so you shouldn't delete it yourself (if you do it, you should call `SetItemData(None)` +to prevent the tree from deleting the pointer second time). The associated data may be retrieved with +:meth:`TreeCtrl.GetItemData` function. + +Working with trees is relatively straightforward if all the items are added to the tree at the moment of +its creation. However, for large trees it may be very inefficient. To improve the performance you may want +to delay adding the items to the tree until the branch containing the items is expanded: so, in the +beginning, only the root item is created (with :meth:`TreeCtrl.AddRoot`). Other items are added when +``EVT_TREE_ITEM_EXPANDING`` event is received: then all items lying immediately under the item being expanded +should be added, but, of course, only when this event is received for the first time for this item - otherwise, +the items would be added twice if the user expands/collapses/re-expands the branch. + +The tree control provides functions for enumerating its items. There are 3 groups of enumeration functions: for +the children of a given item, for the sibling of the given item and for the visible items (those which are +currently shown to the user: an item may be invisible either because its branch is collapsed or because it +is scrolled out of view). Child enumeration functions require the caller to give them a `cookie` parameter: it +is a number which is opaque to the caller but is used by the tree control itself to allow multiple enumerations +to run simultaneously (this is explicitly allowed). The only thing to remember is that the `cookie` passed +to :meth:`TreeCtrl.GetFirstChild` and to :meth:`TreeCtrl.GetNextChild` should be the same variable (and that +nothing should be done with it by the user code). + +Among other features of the tree control are: + +* Item Sorting with :meth:`TreeCtrl.SortChildren` which uses the user-defined comparison function `OnCompareItems` + (by default the comparison is the alphabetic comparison of tree labels); +* Hit Testing (determining to which portion of the control the given point belongs, useful for implementing + drag-and-drop in the tree) with :meth:`TreeCtrl.HitTest`; +* Editing of the tree item labels in place (see :meth:`TreeCtrl.EditLabel`). + +Finally, the tree control has a keyboard interface: the cursor navigation (arrow) keys may be used to change +the current selection. ``HOME`` and ``END`` are used to go to the first/last sibling of the current item. ``+``, +``-`` and ``*`` expand, collapse and toggle the current branch. Note, however, that ``DEL`` and ``INS`` keys +do nothing by default, but it is common to associate them with deleting an item from a tree and inserting +a new one into it. + + +.. seealso:: :ref:`TreeCtrl`, :ref:`ImageList` + + + diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/GridBagSizer.1.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/GridBagSizer.1.py new file mode 100644 index 00000000..3fb4e7ae --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/GridBagSizer.1.py @@ -0,0 +1,46 @@ +##Chris Barker +#!/usr/bin/env python + +""" +A simple test of the GridBagSizer + +http://wiki.wxpython.org/index.cgi/WriteItYourself + +""" + +import wx + +class MyFrame(wx.Frame): + def __init__(self, parent, ID, title): + wx.Frame.__init__(self, parent, ID, title, wx.DefaultPosition) + + Buttons = [] + for i in range(6): + Buttons.append(wx.Button(self,-1, "Button %i"%(i))) + + sizer = wx.GridBagSizer(9, 9) + sizer.Add(Buttons[0], (0, 0), wx.DefaultSpan, wx.ALL, 5) + sizer.Add(Buttons[1], (1, 1), (1,7), wx.EXPAND) + sizer.Add(Buttons[2], (6, 6), (3,3), wx.EXPAND) + sizer.Add(Buttons[3], (3, 0), (1,1), wx.ALIGN_CENTER) + sizer.Add(Buttons[4], (4, 0), (1,1), wx.ALIGN_LEFT) + sizer.Add(Buttons[5], (5, 0), (1,1), wx.ALIGN_RIGHT) + + sizer.AddGrowableRow(6) + sizer.AddGrowableCol(6) + + self.SetSizerAndFit(sizer) + self.Centre() + + +class MyApp(wx.App): + def OnInit(self): + frame = MyFrame(None, -1, "wx.gridbagsizer.py") + frame.Show(True) + self.SetTopWindow(frame) + return True + +if __name__ == "__main__": + app = MyApp(0) + app.MainLoop() + diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/GridBagSizer.2.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/GridBagSizer.2.py new file mode 100644 index 00000000..6442a0cc --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/GridBagSizer.2.py @@ -0,0 +1,43 @@ +##Chris Barker +#!/usr/bin/env python + +import wx + +class TestFrame(wx.Frame): + def __init__(self, *args, **kwargs): + wx.Frame.__init__(self, *args, **kwargs) + + t = wx.TextCtrl(self) + + b1 = wx.Button(self, label="Button1") + b2 = wx.Button(self, label="Button2") + + exitBut = wx.Button(self, label="Exit") + exitBut.Bind(wx.EVT_BUTTON, self.OnCloseWindow) + + sizer = wx.GridBagSizer(10, 10) + sizer.Add(t, (0,0), span=(2,1), flag=wx.ALIGN_CENTER_VERTICAL ) + sizer.Add(b1, (0,1), span=(2,1), flag=wx.ALIGN_CENTER) + sizer.Add(b2, (0,2), flag=wx.ALIGN_CENTER) + + sizer.Add(exitBut, (1,3)) + + self.SetSizerAndFit(sizer) + + wx.EVT_CLOSE(self, self.OnCloseWindow) + + def OnCloseWindow(self, event): + self.Destroy() + +class App(wx.App): + def OnInit(self): + frame = TestFrame(None, title="GridBagSizer Test") + self.SetTopWindow(frame) + frame.Show(True) + return True + +if __name__ == "__main__": + app = App(0) + app.MainLoop() + + diff --git a/etg/_core.py b/etg/_core.py index e7a766e2..0648f15b 100644 --- a/etg/_core.py +++ b/etg/_core.py @@ -19,7 +19,8 @@ DOCSTRING = "" # The classes and/or the basename of the Doxygen XML files to be processed by # this script. ITEMS = [ ] - + + # The list of other ETG scripts and back-end generator modules that are # included as part of this module. These items are in their own etg scripts @@ -228,7 +229,14 @@ def run(): method calls from non-GUI threads. Any extra positional or keyword args are passed on to the callable when it is called. - :see: `CallLater`""", + :param callableObj: the callable object + :param args: arguments to be passed to the callable object + :param kw: keywords to be passed to the callable object + + .. seealso:: + :class:`CallLater` + + """, body="""\ assert callable(callableObj), "callableObj is not callable" app = wx.GetApp() @@ -260,7 +268,15 @@ def run(): the timer completes, automatically cleaning up the wx.CallLater object. - :see: `CallAfter`""", + :param int millis: number of milli seconds + :param callableObj: the callable object + :param args: arguments to be passed to the callable object + :param kw: keywords to be passed to the callable object + + ::seealso: + :func:`CallAfter` + + """, items = [ PyFunctionDef('__init__', '(self, millis, callableObj, *args, **kwargs)', body="""\ @@ -278,7 +294,14 @@ def run(): PyFunctionDef('__del__', '(self)', 'self.Stop()'), PyFunctionDef('Start', '(self, millis=None, *args, **kwargs)', - doc="(Re)start the timer", + doc="""\ + (Re)start the timer + + :param int millis: number of milli seconds + :param args: arguments to be passed to the callable object + :param kw: keywords to be passed to the callable object + + """, body="""\ self.hasRun = False if millis is not None: @@ -312,14 +335,28 @@ def run(): (Re)set the args passed to the callable object. This is useful in conjunction with Restart if you want to schedule a new call to the same callable object but with different - parameters.""", + parameters. + + :param args: arguments to be passed to the callable object + :param kw: keywords to be passed to the callable object + + """, body="""\ self.args = args self.kwargs = kwargs"""), - PyFunctionDef('HasRun', '(self)', 'return self.hasRun'), - PyFunctionDef('GetResult', '(self)', 'return self.result'), - + PyFunctionDef('HasRun', '(self)', 'return self.hasRun', + doc="""\ + :rtype: boolean + + """), + + PyFunctionDef('GetResult', '(self)', 'return self.result', + doc="""\ + :rtype: result from callable + + """), + PyFunctionDef('Notify', '(self)', doc="The timer has expired so call the callable.", body="""\ diff --git a/etg/app.py b/etg/app.py index 7bb86000..1e052c2a 100644 --- a/etg/app.py +++ b/etg/app.py @@ -343,7 +343,7 @@ def run(): app to terminate upon a Ctrl-C in the console like other GUI apps will. - :note: You should override OnInit to do applicaition + :note: You should override OnInit to do application initialization to ensure that the system, toolkit and wxWidgets are fully initialized. """, diff --git a/etgtools/sphinx_generator.py b/etgtools/sphinx_generator.py index 3efba2a8..aba62d87 100644 --- a/etgtools/sphinx_generator.py +++ b/etgtools/sphinx_generator.py @@ -20,6 +20,7 @@ import os import operator import shutil import textwrap +import glob from StringIO import StringIO @@ -41,6 +42,7 @@ from sphinxtools.utilities import FindControlImages, MakeSummary, PickleItem from sphinxtools.utilities import ChopDescription, PythonizeType, Wx2Sphinx from sphinxtools.utilities import PickleClassInfo, IsNumeric from sphinxtools.utilities import Underscore2Capitals, CountSpaces +from sphinxtools.utilities import FormatContributedSnippets from sphinxtools.constants import VERSION, REMOVED_LINKS, SECTIONS from sphinxtools.constants import MAGIC_METHODS, MODULENAME_REPLACE @@ -1512,9 +1514,9 @@ class XRef(Node): else: text = ':ref:`%s`'%Wx2Sphinx(stripped)[1] - - return space_before + text + space_after + ConvertToPython(tail) + return space_before + text + space_after + ConvertToPython(tail) + # ----------------------------------------------------------------------- # @@ -1578,6 +1580,8 @@ class ComputerOutput(Node): text += ConvertToPython(self.element.tail) space_before, space_after = CountSpaces(text) + if space_before == '': + space_before = ' ' return space_before + text + space_after @@ -1626,15 +1630,43 @@ class Emphasis(Node): if self.element.tag == 'emphasis': format = '`%s`' + emphasys = '`' elif self.element.tag == 'bold': format = '**%s**' + emphasys = '**' spacing = ('ParameterList' in self.GetHierarchy() and [' '] or [''])[0] text = Node.Join(self, with_tail=False) - if text.strip(): - text = spacing + format % text.strip() + if self.children: + + startPos = 0 + newText = spacing + + for child in self.children: + childText = child.Join() + + tail = child.element.tail + tail = (tail is not None and [tail] or [''])[0] + + childText = childText.replace(ConvertToPython(tail), '') + fullChildText = child.Join() + endPos = text.index(childText) + + newText += ' ' + emphasys + text[startPos:endPos].strip() + emphasys + ' ' + newText += childText + ' ' + remaining = fullChildText.replace(childText, '') + newText += emphasys + remaining.strip() + emphasys + ' ' + + startPos = endPos + + text = newText + + else: + + if text.strip(): + text = spacing + format % text.strip() if self.element.tail: text += ConvertToPython(self.element.tail) @@ -1776,6 +1808,8 @@ class XMLDocString(object): self.class_name = '' self.snippet_count = 0 + self.contrib_snippets = [] + self.table_count = 0 self.list_level = 1 @@ -1787,7 +1821,7 @@ class XMLDocString(object): self.appearance = [] self.overloads = [] - + if isinstance(xml_item, extractors.MethodDef): self.kind = 'method' elif isinstance(xml_item, (extractors.FunctionDef, extractors.PyFunctionDef)): @@ -2050,13 +2084,29 @@ class XMLDocString(object): dummy, fullname = Wx2Sphinx(name) elif self.kind == 'method': method = self.xml_item - if method.isCtor: + if hasattr(method, 'isCtor') and method.isCtor: method_name = '__init__' + + if hasattr(method, 'className') and method.className is not None: + klass = RemoveWxPrefix(method.className) + else: + klass = RemoveWxPrefix(method.klass.name) + + method_name = '%s.%s'%(klass, method_name) else: method_name = method.name or method.pyName - method_name = RemoveWxPrefix(method_name) - dummy, fullname = Wx2Sphinx(method.className) - fullname = fullname + '.' + method_name + if hasattr(method, 'className') and method.className is not None: + klass = RemoveWxPrefix(method.className) + method_name = '%s.%s'%(klass, method_name) + elif hasattr(method, 'klass'): + klass = RemoveWxPrefix(method.klass.name) + method_name = '%s.%s'%(klass, method_name) + else: + method_name = RemoveWxPrefix(method_name) + method_name = '%s'%method_name + klass = None + + dummy, fullname = Wx2Sphinx(method_name) elif self.kind == 'function': function = self.xml_item name = function.pyName or function.name @@ -2090,7 +2140,17 @@ class XMLDocString(object): converted_py = os.path.join(SNIPPETROOT, 'python', 'converted', fullname + '.%d.py'%self.snippet_count) return cpp_file, python_file, converted_py - + + + def HuntContributedSnippets(self): + + fullname = self.GetFullName() + contrib_folder = os.path.join(SNIPPETROOT, 'python', 'contrib') + + possible_py = glob.glob(os.path.normpath(contrib_folder + '/' + fullname + '*.py')) + + return possible_py + # ----------------------------------------------------------------------- @@ -2159,6 +2219,13 @@ class XMLDocString(object): subs_desc = templates.TEMPLATE_SUBCLASSES % subs stream.write(subs_desc) + possible_py = self.HuntContributedSnippets() + + if possible_py: + possible_py.sort() + snippets = FormatContributedSnippets(self.kind, possible_py) + stream.write(snippets) + if klass.method_list: summary = MakeSummary(name, klass.method_list, templates.TEMPLATE_METHOD_SUMMARY, 'meth') stream.write(summary) @@ -2381,6 +2448,14 @@ class XMLDocString(object): stream.write('\n\n') self.Reformat(stream) + + possible_py = self.HuntContributedSnippets() + + if possible_py: + possible_py.sort() + snippets = FormatContributedSnippets(self.kind, possible_py) + stream.write(snippets) + stream.write("\n\n") if not self.is_overload and write: @@ -2418,6 +2493,13 @@ class XMLDocString(object): self.Reformat(stream) + possible_py = self.HuntContributedSnippets() + + if possible_py: + possible_py.sort() + snippets = FormatContributedSnippets(self.kind, possible_py) + stream.write(snippets) + if not self.is_overload and write: PickleItem(stream.getvalue(), self.current_module, name, 'function') @@ -2494,8 +2576,11 @@ class XMLDocString(object): newline = line if 'supports the following styles:' in line: - docstrings += templates.TEMPLATE_WINDOW_STYLES % class_name - + if class_name is not None: + # Crappy wxWidgets docs!!! They put the Window Styles inside the + # constructor!!! + docstrings += templates.TEMPLATE_WINDOW_STYLES % class_name + elif 'The following event handler macros' in line: last = line.index(':') line = line[last+1:].strip() @@ -2935,12 +3020,18 @@ class SphinxGenerator(generators.DocsGeneratorBase): stream = StringIO() stream.write('\n .. method:: %s%s\n\n' % (pm.name, pm.argsString)) - docstrings = ConvertToPython(pm.pyDocstring).replace('\n', ' ') +## docstrings = ConvertToPython(pm.pyDocstring).replace('\n', ' ') + docstrings = ConvertToPython(pm.pyDocstring) newdocs = '' + spacer = ' '*6 + for line in docstrings.splitlines(): - newdocs += ' '*6 + line + "\n" - + if not line.startswith(spacer): + newdocs += spacer + line + "\n" + else: + newdocs += line + "\n" + stream.write(newdocs + '\n\n') name = RemoveWxPrefix(self.current_class.name) or self.current_class.pyName diff --git a/sphinxtools/constants.py b/sphinxtools/constants.py index 9adea49e..015b37ff 100644 --- a/sphinxtools/constants.py +++ b/sphinxtools/constants.py @@ -144,7 +144,7 @@ HTML_REPLACE = ['module', 'function', 'method', 'class', 'classmethod', 'staticm # The SVN revision of wxWidgets/Phoenix used to build the Sphinx docs. # There must be a more intelligent way to get this information automatically. -SVN_REVISION = '71022' +SVN_REVISION = '71066' # Today's date representation for the Sphinx HTML docs TODAY = datetime.date.today().strftime('%d %B %Y') diff --git a/sphinxtools/postprocess.py b/sphinxtools/postprocess.py index ed1442c5..f481ecc4 100644 --- a/sphinxtools/postprocess.py +++ b/sphinxtools/postprocess.py @@ -145,7 +145,10 @@ def BuildEnumsAndMethods(sphinxDir): text = text.replace(':note:', '.. note::') text = text.replace(':see:', '.. seealso::') text = text.replace('`String`&', 'string') - + text = text.replace('See also\n', '.. seealso:: ') + # Avoid Sphinx warnings on wx.TreeCtrl + text = text.replace('**( `', '** ( `') + if text != orig_text: fid = open(input, 'wt') fid.write(text) @@ -184,8 +187,14 @@ def BuildEnumsAndMethods(sphinxDir): # ----------------------------------------------------------------------- # def FindInherited(input, class_summary, enum_base, text): - - regex = re.findall(':meth:\S+', text) + + # Malformed inter-links + regex = re.findall(r'\S:meth:\S+', text) + for regs in regex: + newreg = regs[0] + ' ' + regs[1:] + text = text.replace(regs, newreg) + + regex = re.findall(r':meth:\S+', text) for regs in regex: @@ -304,20 +313,25 @@ def ReformatFunctions(file): label = local_file.split('.')[0:-2][0] names = functions.keys() + names = [name.lower() for name in names] names.sort() text = templates.TEMPLATE_FUNCTION_SUMMARY % (label, label) letters = [] for fun in names: - if fun[0] not in letters: - letters.append(fun[0].upper()) + upper = fun[0].upper() + if upper not in letters: + letters.append(upper) - text += ' | '.join(['`%s`_'%letter for letter in letters]) + text += ' | '.join([':ref:`%s <%s %s>`'%(letter, label, letter) for letter in letters]) text += '\n\n\n' + names = functions.keys() + names = sorted(names, key=str.lower) + for letter in letters: - text += '%s\n^\n\n'%letter + text += '.. _%s %s:\n\n%s\n^\n\n'%(label, letter, letter) for fun in names: if fun[0].upper() != letter: continue diff --git a/sphinxtools/templates.py b/sphinxtools/templates.py index 30aabc1f..f34b0de7 100644 --- a/sphinxtools/templates.py +++ b/sphinxtools/templates.py @@ -198,6 +198,12 @@ TEMPLATE_EVENTS = ''' ''' +TEMPLATE_CONTRIB = ''' + +|user| Contributed Examples +=========================== + +''' # Template used to generate the widgets gallery (this needs some work) TEMPLATE_GALLERY = ''' diff --git a/sphinxtools/utilities.py b/sphinxtools/utilities.py index 7d6baf7f..89772810 100644 --- a/sphinxtools/utilities.py +++ b/sphinxtools/utilities.py @@ -19,6 +19,8 @@ import cPickle from UserDict import UserDict # Phoenix-specific imports +from templates import TEMPLATE_CONTRIB + from constants import IGNORE, PUNCTUATION from constants import CPP_ITEMS, VERSION, VALUE_MAP from constants import RE_KEEP_SPACES @@ -587,3 +589,31 @@ def Wx2Sphinx(name): # ----------------------------------------------------------------------- # + +def FormatContributedSnippets(kind, contrib_snippets): + + spacer = '' + if kind == 'function': + spacer = 3*' ' + elif kind == 'method': + spacer = 6*' ' + + if kind == 'class': + text = TEMPLATE_CONTRIB + else: + text = spacer + '\n**Contributed Examples:**\n\n' + + for indx, snippet in enumerate(contrib_snippets): + fid = open(snippet, 'rt') + lines = fid.readlines() + fid.close() + user = lines[0].replace('##', '').strip() + + text += '\n' + spacer + 'Example %d (%s)::\n\n'%(indx+1, user) + + for line in lines[1:]: + text += 4*' '+ spacer + line + + text += '\n' + + return text