better docstrings

you now see:

class_method(cls, *args, **kwargs) method of gi.types.GObjectMeta
instance
    make a black image
    usage:
       out = Vips.Image.black(width, height, bands = gint)

    where:
       out        - Output image, VipsImage

    required parameters:
       width      - Image width in pixels, gint
       height     - Image height in pixels, gint

    optional parameters:
       bands      - Number of bands in image, gint
This commit is contained in:
John Cupitt 2014-11-13 14:37:59 +00:00
parent f8200d67a8
commit 6a25b04974
4 changed files with 95 additions and 86 deletions
TODO
libvips
include/vips
iofuncs
python

82
TODO

@ -29,86 +29,16 @@
op = Vips.Operation.new("black")
help(op)
- want to get the description for an operation
but does not include our docstring, strange
op = Vips.Operation.new("black")
this has stuff from comments in Vips.py
can't look at op.description, since that's not set until build(), we need to
get the class and walk that
help(Vips.Image)
try:
we should trim and rewrite comments
GType a = Vips.type_find("VipsObject", "black")
in C, use this to get the class from a gtype:
g_type_class_ref(gtype)
from gi.repository import GObject
dir(GObject.GType)
['__class__', '__delattr__', '__doc__', '__eq__', '__format__',
'__ge__', '__getattribute__', '__gt__', '__hash__', '__init__',
'__le__', '__lt__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__', 'children', 'depth', 'from_name', 'fundamental',
'has_value_table', 'interfaces', 'is_a', 'is_abstract', 'is_classed',
'is_deep_derivable', 'is_derivable', 'is_instantiatable',
'is_interface', 'is_value_abstract', 'is_value_type', 'name',
'parent', 'pytype']
a = Vips.type_find("VipsObject", "black")
dir(a)
['__class__', '__delattr__', '__doc__', '__eq__', '__format__',
'__ge__', '__getattribute__', '__gt__', '__hash__', '__init__',
'__le__', '__lt__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__', 'children', 'depth', 'from_name', 'fundamental',
'has_value_table', 'interfaces', 'is_a', 'is_abstract', 'is_classed',
'is_deep_derivable', 'is_derivable', 'is_instantiatable',
'is_interface', 'is_value_abstract', 'is_value_type', 'name',
'parent', 'pytype']
>>> op = Vips.Operation.new("black")
>>> dir(op)
['__class__', '__copy__', '__deepcopy__', '__delattr__', '__dict__',
'__doc__', '__eq__', '__format__', '__gdoc__', '__ge__',
'__getattribute__', '__gpointer__', '__grefcount__', '__gsignals__',
'__gt__', '__gtype__', '__hash__', '__info__', '__init__', '__le__',
'__lt__', '__module__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__', '_force_floating', '_ref', '_ref_sink', '_unref',
'_unsupported_data_method', '_unsupported_method', 'argument_isset',
'argument_needsstring', 'argument_table', 'bind_property',
'bind_property_full', 'build', 'chain', 'close', 'compat_control',
'connect', 'connect_after', 'connect_object', 'connect_object_after',
'constructed', 'description', 'disconnect', 'disconnect_by_func',
'do_build', 'do_close', 'do_get_flags', 'do_invalidate',
'do_output_to_arg', 'do_postbuild', 'do_postclose', 'do_preclose',
'do_rewind', 'emit', 'emit_stop_by_name', 'force_floating',
'found_hash', 'freeze_notify', 'g_type_instance',
'get_argument_flags', 'get_argument_priority',
'get_argument_to_string', 'get_data', 'get_flags', 'get_properties',
'get_property', 'get_qdata', 'handler_block', 'handler_block_by_func',
'handler_disconnect', 'handler_is_connected', 'handler_unblock',
'handler_unblock_by_func', 'hash', 'interface_find_property',
'interface_install_property', 'interface_list_properties',
'invalidate', 'is_floating', 'local_cb', 'local_memory', 'new',
'new_from_string', 'nickname', 'notify', 'notify_by_pspec',
'parent_instance', 'parent_object', 'pixels', 'postclose', 'preclose',
'print_all', 'print_dump', 'print_name', 'print_summary',
'print_summary_class', 'props', 'qdata', 'ref', 'ref_count',
'ref_sink', 'replace_data', 'replace_qdata', 'rewind', 'run_dispose',
'sanity', 'sanity_all', 'set_argument_from_string', 'set_data',
'set_from_string', 'set_properties', 'set_property', 'set_required',
'set_static', 'static_object', 'steal_data', 'steal_qdata',
'stop_emission', 'stop_emission_by_name', 'thaw_notify', 'unref',
'unref_outputs', 'watch_closure', 'weak_ref']
- python fitsload has both "access" and "sequential" as kwargs, is this right?
why do we need both?
- test other arg types

@ -639,6 +639,8 @@ void vips_object_rewind( VipsObject *object );
void vips_object_unref_outputs( VipsObject *object );
const char *vips_object_get_description( VipsObject *object );
#ifdef __cplusplus
}
#endif /*__cplusplus*/

@ -2974,3 +2974,26 @@ vips_object_unref_outputs( VipsObject *object )
(void) vips_argument_map( object,
vips_object_unref_outputs_sub, NULL, NULL );
}
/**
* vips_object_get_description:
* @object: object to fetch description from
*
* Fetch the object description. Useful for language bindings.
*
* @object.description is only avaliable after _build(), which can be too
* late. This function fetches from the instance, if possible, but falls back
* to the class description if we are too early.
*
* Returns: the object description
*/
const char *
vips_object_get_description( VipsObject *object )
{
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
if( object->description )
return( object->description ) ;
else
return( class->description ) ;
}

@ -157,6 +157,13 @@ class Argument:
return value
def description(self):
result = self.name
result += " " * (10 - len(self.name)) + " - " + self.prop.blurb
result += ", " + self.prop.value_type.name
return result
Vips.Argument = Argument
# search a list recursively for a Vips.Image object
@ -391,15 +398,61 @@ def generate_docstring(name):
not x.isset]
required_output = [x for x in args if x.flags & enm.OUTPUT and
not x.flags & enm.REQUIRED]
x.flags & enm.REQUIRED]
optional_output = [x for x in args if x.flags & enm.OUTPUT and
not x.flags & enm.REQUIRED]
result = "usage:\n"
# find the first required input image, if any ... we will be a member
# function of this instance
member_x = None
for i in range(0, len(required_input)):
x = required_input[i]
if GObject.type_is_a(vips_type_image, x.prop.value_type):
member_x = x
break
result = op.get_description() + "\n"
result += "usage:\n"
result += " " + ", ".join([x.name for x in required_output]) + " = "
if member_x:
result += member_x.name + "." + name + "("
else:
result += "Vips.Image." + name + "("
result += ", ".join([x.name for x in required_input
if x != member_x])
if len(optional_input) > 0:
result += ", "
result += ", ".join([x.name + " = " + x.prop.value_type.name
for x in optional_input])
result += ")\n"
result += "\n"
result += "where:\n"
for x in required_output:
result += " " + x.description() + "\n"
result += "\n"
result += "required parameters:\n"
for x in required_input:
result += x.name + "\n"
result += " " + x.description() + "\n"
if len(optional_input) > 0:
result += "\n"
result += "optional parameters:\n"
for x in optional_input:
result += " " + x.description() + "\n"
if len(optional_output) > 0:
result += "\n"
result += "extra output options:\n"
for x in optional_output:
result += " " + x.description() + "\n"
return result
@ -412,6 +465,13 @@ def smap(func, x):
else:
return func(x)
# decorator to set docstring
def add_doc(value):
def _doc(func):
func.__doc__ = value
return func
return _doc
class Image(Vips.Image):
"""This is a test docstring in Vips.py ... does this get attached to the
class we are overriding?
@ -455,9 +515,9 @@ class Image(Vips.Image):
if name in dir(self.props):
return getattr(self.props, name)
@add_doc(generate_docstring(name))
def call_function(*args, **kwargs):
return _call_instance(self, name, args, kwargs)
call_function.__doc__ = generate_docstring(name)
return call_function
@ -788,12 +848,6 @@ class_methods = [
"fitsload",
"openexrload"]
def add_doc(value):
def _doc(func):
func.__doc__ = value
return func
return _doc
def generate_class_method(name):
@classmethod
@add_doc(generate_docstring(name))