Source code for camelot.core.document

#  ============================================================================
#
#  Copyright (C) 2007-2016 Conceptive Engineering bvba.
#  www.conceptive.be / info@conceptive.be
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions are met:
#      * Redistributions of source code must retain the above copyright
#        notice, this list of conditions and the following disclaimer.
#      * Redistributions in binary form must reproduce the above copyright
#        notice, this list of conditions and the following disclaimer in the
#        documentation and/or other materials provided with the distribution.
#      * Neither the name of Conceptive Engineering nor the
#        names of its contributors may be used to endorse or promote products
#        derived from this software without specific prior written permission.
#  
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#  DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
#  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#  ============================================================================
"""Decorators to enhance the docstrings of classes
"""

import six

from sqlalchemy import inspect, orm, util

from ...admin.entity_admin import EntityAdmin

[docs]def document_classes(classes): """Append mapped property documentation to the docstring of a class :param classes: the list of classes to document """ def document_column_property(cls, key, prop): docstrings = [] if isinstance(prop, orm.ColumnProperty): attrs = EntityAdmin.get_sql_field_attributes(prop.columns) python_type = attrs.get('python_type', None) if prop.doc: docstrings.append( prop.doc ) if isinstance(python_type, type): docstrings.append( python_type.__name__ ) if attrs.get('nullable', True): docstrings.append('not required' ) else: docstrings.append('required' ) length = attrs.get('length', None) if length is not None: docstrings.append('length : {}'.format(length) ) precision = attrs.get('precision', None) if precision is not None: docstrings.append('precision : {}'.format(precision) ) for column in prop.columns: for foreign_key in column.foreign_keys: docstrings.append('foreign key to {}'.format(foreign_key.column)) choices = attrs.get('choices', None) if (choices is not None) and (isinstance(choices, list)): values = [six.text_type(v) for v, _s in choices] docstrings.append('possible values : {}'.format('/'.join(values))) if len(docstrings): setattr( getattr(cls,key), '__doc__', ', '.join(docstrings) ) def document_relationship_property(cls, key, prop): docstrings = [] if isinstance(prop, orm.properties.RelationshipProperty): target = prop.mapper.class_ if target is not None: if isinstance(target, six.string_types): docstrings.append('points to :class:`{0}`'.format(target)) else: docstrings.append('points to :class:`{0.__module__}.{0.__name__}`'.format(target)) if len(docstrings): return '{0} : {1}'.format(key, u', '.join(docstrings)) def document_class(model): # # Add documentation on its fields # documented_fields = [] mapper = inspect(model) if mapper.mapped_table is not None: mapped_to = six.text_type(mapper.mapped_table) # this is a hack to use the items method of ImmutableProperties, without # triggering the PY3K convertor for key, value in util.ImmutableProperties.items(mapper.column_attrs): doc = document_column_property( cls, key, value ) for key, value in util.ImmutableProperties.items(mapper.relationships): doc = document_relationship_property( cls, key, value ) if doc: documented_fields.append( doc ) model.__doc__ = (model.__doc__ or '') + """ .. image:: /_static/entityviews/new_view_%s.png mapped to %s """%(model.__name__.lower(), mapped_to) + ''.join('\n * %s'%(doc) for doc in documented_fields) for cls in classes: document_class(cls)