Skip to content

Commit

Permalink
Docstring support
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.dsource.org/projects/pyd/trunk@59 1df65b71-e716-0410-9316-ac55df2b1602
  • Loading branch information
KirkMcDonald authored and KirkMcDonald committed Dec 16, 2006
1 parent d30f0e5 commit a771885
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 33 deletions.
2 changes: 1 addition & 1 deletion html_doc/basics.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ <h3>Module basics</h3>

<p>The <code>module_init</code> function has the following form:</p>

<p><code>PyObject* module_init(char[] <span class="arg">name</span>);</code></p>
<p><code>PyObject* module_init(char[] <span class="arg">name</span>, char[] <span class="arg">docstring</span>="");</code></p>

<p>It does little more than call <a href="http://docs.python.org/api/allocating-objects.html">Py_InitModule</a> and return the new module object. This object is also available via the <code>Pyd_Module_p</code> property once you've called <code>module_init</code>.</p>

Expand Down
11 changes: 6 additions & 5 deletions html_doc/class_wrapping.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,19 @@ <h1>Class wrapping</h1>
<p>To expose the constructors, methods, and properties of the class, <code>wrapped_class</code> provides a series of template member functions.</p>

<dl>
<dt><code>static void def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn)) ();</code></dt>
<dt><code>static void def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn)) (char[] <span class="arg">docstring</span>="");</code></dt>
<dd>This wraps a method of the class. It functions exactly like the <code>def</code> function used to <a href="func_wrapping.html">wrap regular functions</a>, with one very important difference: There is no support for default arguments. (This is a side-effect of the fact that you cannot call an alias of a method in D, and delegates do not understand default arguments.)</dd>

<dt><code>static void static_def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn), uint <span class="t_arg">MIN_ARGS</span> = minArgs!(fn)) ();</code></dt>
<dt><code>static void static_def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn), uint <span class="t_arg">MIN_ARGS</span> = minArgs!(fn)) (char[] <span class="arg">docstring</span>="");</code></dt>
<dd>This wraps a static member function of the class. It also functions exactly like the <code>def</code> function used to wrap regular functions, and even includes support for default arguments.</dd>

<dt><code>static void prop(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), bool <span class="t_arg">RO</span> = false) ();</code></dt>
<dt><code>static void prop(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), bool <span class="t_arg">RO</span> = false) (char[] <span class="arg">docstring</span>="");</code></dt>
<dd>This wraps a property. See the examples below for more details.
<ul>
<li><span class="t_arg">fn</span> is the name of the property. <code>prop</code> will automatically attempt to wrap both the "get" and "set" forms of the property, unless <span class="t_arg">RO</span> is specified.</li>
<li><span class="t_arg">name</span> is the name of the property as it will appear in Python. As with <code>def</code>, <code>prop</code> will attempt to derive this automatically.</li>
<li><span class="t_arg">RO</span> specifies whether this is a <i>read-only</i> property. If true, it will only wrap the "get" form of the property. If false, it will wrap both the "get" and "set" forms. <i>(This is a little hackish, and I will probably try to make this detection more automatic in the future. It also means it cannot support a property that only has a "set" form.)</i></li>
<li><span class="arg">docstring</span> is the property's docstring. As usual, note that this is a regular function argument, and not a template argument.</li>
</ul>
</dd>

Expand All @@ -59,14 +60,14 @@ <h1>Class wrapping</h1>
<dt><code>static void iter(<span class="t_arg">iter_t</span>) ();</code></dt>
<dd>This allows the user to specify a different overload of opApply than the default. (The default is always the one that is lexically first.) The <span class="t_arg">iter_t</span> argument should be the type of the delegate that forms the argument to opApply. This might be e.g. <code>int delegate(inout int)</code>. Don't forget the <code>inout</code> modifiers!</dd>

<dt><code>static void alt_iter(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">iter_t</span> = <i>implementationDetail</i>) ();</code></dt>
<dt><code>static void alt_iter(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">iter_t</span> = <i>implementationDetail</i>) (char[] <span class="arg">docstring</span>="");</code></dt>
<dd>This wraps alternate iterator methods as Python methods that return iterator objects. The wrapped methods should have a signature like that of opApply. (In other words, they should be methods intended to be used with D's ability to iterate over delgates.) The <span class="t_arg">iter_t</span> argument should be the type of the delegate argument to the method. This will usually be derived automatically.
</dd>
</dl>

<p>Once you have called all of the member functions of <code>wrapped_class</code> that you wish to, you must issue a call to <code>finalize_class</code>.</p>

<p><code>void finalize_class(<span class="t_arg">CLS</span>) (<span class="t_arg">CLS</span> <span class="arg">cls</span>);</code></p>
<p><code>void finalize_class(<span class="t_arg">CLS</span>) (<span class="t_arg">CLS</span> <span class="arg">cls</span>, char[] <span class="arg">docstring</span>="");</code></p>

<p>This does some final initialization of the class and then registers it with Python. Unlike calls to <a href="func_wrapping.html"><code>def</code></a>, calls to <code>finalize_class</code> must occur <em>after</em> calling <code>module_init</code>. The <span class="arg">cls</span> function argument should be an instance of <code>wrapped_class</code>.</p>

Expand Down
3 changes: 2 additions & 1 deletion html_doc/func_wrapping.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,13 @@ <h1>Function wrapping</h1>

<p>Exposing D functions to Python is easy! The heart of Pyd's function wrapping features is the <code>def</code> template function:</p>

<p><code>void def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn), uint <span class="t_arg">MIN_ARGS</span> = minArgs!(fn)) ();</code></p>
<p><code>void def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn), uint <span class="t_arg">MIN_ARGS</span> = minArgs!(fn)) (char[] <span class="arg">docstring</span>="");</code></p>
<ul>
<li><span class="t_arg">fn</span> is the function to wrap. Note that this is an alias parameter. <code>def</code> is only capable of wrapping full-fledged functions, not function pointers, function literals, or delegates.</li>
<li><span class="t_arg">name</span> is the name the function will have inside of Python. Usually, you don't have to specify this. (Special thanks to Don Clugston's Nameof module.)</li>
<li><span class="t_arg">fn_t</span> is the function type of the function. Typically, you won't have to specify this. It is used to wrap overloaded functions. (See below.)</li>
<li><span class="t_arg">MIN_ARGS</span> is the minimum number of arguments this function can accept. It is used when a function has default arguments. The <code>minArgs</code> template can derive the correct number automatically, so you typically won't specify this manually.</li>
<li><span class="arg">docstring</span> is the function's docstring. Note that this is a regular function argument!</li>
</ul>

<p>All calls to <code>def</code> must occur <em>before</em> calling <code>module_init</code>. Any function whose return type and arguments are <a href="conversion.html">convertible</a> can be wrapped by <code>def</code>. <code>def</code> can only wrap functions with <code>in</code> arguments (not <code>out</code> or <code>inout</code> or <code>lazy</code>). <code>def</code> also provides support for wrapping overloaded functions as well as functions with default arguments. Here are some examples:</p>
Expand Down
12 changes: 6 additions & 6 deletions html_doc/struct_wrapping.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,30 +38,30 @@ <h1>Struct wrapping</h1>
<p>To expose the data members, member functions, and properties of the class, <code>wrapped_struct</code> provides a series of template member functions.</p>

<dl>
<dt><code>static void member(<span class="t_arg">M</span>, size_t <span class="t_arg">offset</span>, char[] <span class="t_arg">name</span>) ();</code></dt>
<dt><code>static void member(<span class="t_arg">M</span>, size_t <span class="t_arg">offset</span>, char[] <span class="t_arg">name</span>) (char[] <span class="arg">docstring</span>="");</code></dt>
<dd>This exposes a data member of the struct to Python. <span class="t_arg">M</span> is the type of the member, and must be a <a href="conversion.html">convertible type</a>. <span class="t_arg">offset</span> is the offset (in bytes) of the member in the struct. <span class="t_arg">name</span> is the name of the data member as it will be used in Python. <i>(Optimally, one would simply be able to pass an alias to the member, or at worst an alias and a name, but DMD currently has some issues with this.)</i></dd>

<dt><code>static void def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn)) ();</code></dt>
<dt><code>static void def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn)) (char[] <span class="arg">docstring</span>="");</code></dt>
<dd>This wraps a member function of the struct. It functions exactly like the <code>def</code> function used to <a href="class_wrapping.html">wrap class methods</a>, including the lack of support for default arguments.</dd>

<dt><code>static void static_def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn), uint <span class="t_arg">MIN_ARGS</span> = minArgs!(fn)) ();</code></dt>
<dt><code>static void static_def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn), uint <span class="t_arg">MIN_ARGS</span> = minArgs!(fn)) (char[] <span class="arg">docstring</span>="");</code></dt>
<dd>This wraps a static member function of the struct. It functions exactly like the <code>static_def</code> function used to wrap static class member functions, and also includes support for default arguments.</dd>

<dt><code>static void prop(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), bool <span class="t_arg">RO</span> = false) ();</code></dt>
<dt><code>static void prop(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), bool <span class="t_arg">RO</span> = false) (char[] <span class="arg">docstring</span>="");</code></dt>
<dd>This wraps a property. It is identical to the <code>prop</code> function used to <a href="class_wrapping.html">wrap class properties</a>.</dd>

<dt><code>static void iter(<span class="t_arg">iter_t</span>) ();</code></dt>
<dd>This allows the user to specify a different overload of opApply than the default. (The default is always the one that is lexically first.) It is identical to the <code>iter</code> function used in <a href="class_wrapping.html">class wrapping</a>.</dd>

<dt><code>static void alt_iter(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">iter_t</span> = <i>implementationDetail</i>) ();</code></dt>
<dt><code>static void alt_iter(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">iter_t</span> = <i>implementationDetail</i>) (char[] <span class="arg">docstring</span>="");</code></dt>
<dd>This wraps alternate iterator methods as Python methods that return iterator objects. It is is identical to the <code>alt_iter</code> function used in <a href="class_wrapping.html">class wrapping</a>.</dd>
</dl>

<p><i>(Future enhancements: Support for struct ctors.)</i></p>

<p>Once you have called all of the member functions of <code>wrapped_struct</code> that you wish to, you must issue a call to <code>finalize_struct</code>.</p>

<p><code>void finalize_struct(<span class="t_arg">S</span>) (<span class="t_arg">S</span> <span class="arg">s</span>);</code></p>
<p><code>void finalize_struct(<span class="t_arg">S</span>) (<span class="t_arg">S</span> <span class="arg">s</span>, char[] <span class="arg">docstring</span>="");</code></p>

<p>This does some final initialization of the type and then registers it with Python. As with calls to <a href="class_wrapping.html"><code>finalize_class</code></a>, calls to <code>finalize_struct</code> must occur <em>after</em> calling <code>module_init</code>. The <span class="arg">s</span> function argument should be an instance of <code>wrapped_struct</code>.</p>

Expand Down
20 changes: 10 additions & 10 deletions infrastructure/pyd/class_wrap.d
Original file line number Diff line number Diff line change
Expand Up @@ -250,14 +250,14 @@ struct wrapped_class(T, char[] classname = symbolnameof!(T)) {
* fn_t = The type of the function. It is only useful to specify this
* if more than one function has the same name as this one.
*/
static void def(alias fn, char[] name = symbolnameof!(fn), fn_t=typeof(&fn)) () {
static void def(alias fn, char[] name = symbolnameof!(fn), fn_t=typeof(&fn)) (char[] docstring="") {
pragma(msg, "class.def: " ~ name);
static PyMethodDef empty = { null, null, 0, null };
alias wrapped_method_list!(T) list;
list[length-1].ml_name = (name ~ \0).ptr;
list[length-1].ml_meth = &method_wrap!(T, fn, fn_t).func;
list[length-1].ml_flags = METH_VARARGS;
list[length-1].ml_doc = "";
list[length-1].ml_doc = (docstring ~ \0).ptr;
list ~= empty;
// It's possible that appending the empty item invalidated the
// pointer in the type struct, so we renew it here.
Expand All @@ -267,14 +267,14 @@ struct wrapped_class(T, char[] classname = symbolnameof!(T)) {
/**
* Wraps a static member function of the class. Identical to pyd.def.def
*/
static void static_def(alias fn, char[] name = symbolnameof!(fn), fn_t=typeof(&fn), uint MIN_ARGS=minArgs!(fn)) () {
static void static_def(alias fn, char[] name = symbolnameof!(fn), fn_t=typeof(&fn), uint MIN_ARGS=minArgs!(fn)) (char[] docstring="") {
pragma(msg, "class.static_def: " ~ name);
static PyMethodDef empty = { null, null, 0, null };
alias wrapped_method_list!(T) list;
list[length-1].ml_name = (name ~ \0).ptr;
list[length-1].ml_meth = &function_wrap!(fn, MIN_ARGS, fn_t).func;
list[length-1].ml_flags = METH_VARARGS | METH_STATIC;
list[length-1].ml_doc = "";
list[length-1].ml_doc = (docstring ~ \0).ptr;
list ~= empty;
wrapped_class_type!(T).tp_methods = list;
}
Expand All @@ -287,7 +287,7 @@ struct wrapped_class(T, char[] classname = symbolnameof!(T)) {
* name = The name of the property as it will appear in Python.
* RO = Whether this is a read-only property.
*/
static void prop(alias fn, char[] name = symbolnameof!(fn), bool RO=false) () {
static void prop(alias fn, char[] name = symbolnameof!(fn), bool RO=false) (char[] docstring="") {
pragma(msg, "class.prop: " ~ name);
static PyGetSetDef empty = { null, null, null, null, null };
wrapped_prop_list!(T)[length-1].name = (name ~ \0).ptr;
Expand All @@ -297,7 +297,7 @@ struct wrapped_class(T, char[] classname = symbolnameof!(T)) {
wrapped_prop_list!(T)[length-1].set =
&wrapped_set!(T, fn).func;
}
wrapped_prop_list!(T)[length-1].doc = "";
wrapped_prop_list!(T)[length-1].doc = (docstring ~ \0).ptr;
wrapped_prop_list!(T)[length-1].closure = null;
wrapped_prop_list!(T) ~= empty;
// It's possible that appending the empty item invalidated the
Expand Down Expand Up @@ -341,14 +341,14 @@ struct wrapped_class(T, char[] classname = symbolnameof!(T)) {
* D's delegate-as-iterator features, as methods returning a Python
* iterator.
*/
static void alt_iter(alias fn, char[] name = symbolnameof!(fn), iter_t = funcDelegInfoT!(typeof(&fn)).Meta.ArgType!(0)) () {
static void alt_iter(alias fn, char[] name = symbolnameof!(fn), iter_t = funcDelegInfoT!(typeof(&fn)).Meta.ArgType!(0)) (char[] docstring="") {
static PyMethodDef empty = { null, null, 0, null };
alias wrapped_method_list!(T) list;
PydStackContext_Ready();
list[length-1].ml_name = name ~ \0;
list[length-1].ml_meth = cast(PyCFunction)&wrapped_iter!(T, fn, int function(iter_t)).iter;
list[length-1].ml_flags = METH_VARARGS;
list[length-1].ml_doc = "";
list[length-1].ml_doc = (docstring ~ \0).ptr;
list ~= empty;
// It's possible that appending the empty item invalidated the
// pointer in the type struct, so we renew it here.
Expand All @@ -362,7 +362,7 @@ struct wrapped_class(T, char[] classname = symbolnameof!(T)) {
* Finalize the wrapping of the class. It is neccessary to call this after all
* calls to the wrapped_class member functions.
*/
void finalize_class(CLS) (CLS cls, char[] modulename="") {
void finalize_class(CLS) (CLS cls, char[] docstring="", char[] modulename="") {
alias CLS.wrapped_type T;
alias wrapped_class_type!(T) type;
const char[] name = CLS._name;
Expand All @@ -378,7 +378,7 @@ void finalize_class(CLS) (CLS cls, char[] modulename="") {
// Fill in missing values
type.ob_type = PyType_Type_p();
type.tp_basicsize = (wrapped_class_object!(T)).sizeof;
type.tp_doc = (name ~ " objects" ~ \0).ptr;
type.tp_doc = (docstring ~ \0).ptr;
type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
//type.tp_repr = &wrapped_repr!(T).repr;
type.tp_methods = wrapped_method_list!(T).ptr;
Expand Down
Loading

0 comments on commit a771885

Please sign in to comment.