コード例 #1
0
def get_validation_description(view, method):
    """
    Returns validation description in format:
    ### Validation:
    validate method docstring
    * field1 name
     * field1 validation docstring
    * field2 name
     * field2 validation docstring
    """
    if method not in ('PUT', 'PATCH',
                      'POST') or not hasattr(view, 'get_serializer'):
        return ''

    serializer = view.get_serializer()
    description = ''
    if hasattr(serializer,
               'validate') and serializer.validate.__doc__ is not None:
        description += formatting.dedent(
            smart_text(serializer.validate.__doc__))

    for field in serializer.fields.values():
        if not hasattr(serializer, 'validate_' + field.field_name):
            continue

        field_validation = getattr(serializer, 'validate_' + field.field_name)

        if field_validation.__doc__ is not None:
            docstring = formatting.dedent(smart_text(
                field_validation.__doc__)).replace('\n', '\n\t')
            field_description = '* %s\n * %s' % (field.field_name, docstring)
            description += ('\n' + field_description
                            if description else field_description)

    return '### Validation:\n' + description if description else ''
コード例 #2
0
ファイル: views.py プロジェクト: nijel/weblate
def get_view_description(view_cls, html=False):
    """
    Given a view class, return a textual description to represent the view.
    This name is used in the browsable API, and in OPTIONS responses.

    This function is the default for the `VIEW_DESCRIPTION_FUNCTION` setting.
    """
    description = view_cls.__doc__ or ''
    description = formatting.dedent(smart_text(description))

    if hasattr(getattr(view_cls, 'serializer_class', 'None'), 'Meta'):
        doc_url = get_doc_url(
            'api',
            '{0}s'.format(
                view_cls.serializer_class.Meta.model.__name__.lower()
            )
        )
    else:
        doc_url = get_doc_url('api')

    if html:
        return (
            formatting.markup_description(description) +
            mark_safe(DOC_TEXT.format(doc_url))
        )
    return description
コード例 #3
0
def get_view_description(view_cls, html=False):
    """
    Given a view class, return a textual description to represent the view.
    This name is used in the browsable API, and in OPTIONS responses.

    This function is the default for the `VIEW_DESCRIPTION_FUNCTION` setting.
    """
    description = view_cls.__doc__ or ''
    description = formatting.dedent(smart_text(description))

    if hasattr(view_cls, 'serializer_class'):
        doc_url = get_doc_url(
            'api'
            '{0}s'.format(
                view_cls.serializer_class.Meta.model.__name__.lower()
            )
        )
    else:
        doc_url = get_doc_url('api')

    description = '\n\n'.join((
        description,
        DOC_TEXT.format(doc_url)
    ))

    if html:
        return formatting.markup_description(description)
    return description
コード例 #4
0
    def get_description(self, path, method, view):
        """
        Determine a link description.

        This will be based on the method docstring if one exists,
        or else the class docstring.
        """
        method_name = getattr(view, 'action', method.lower())
        method_docstring = getattr(view, method_name, None).__doc__
        if method_docstring:
            # An explicit docstring on the method or action.
            return formatting.dedent(smart_text(method_docstring))

        description = view.get_view_description()
        lines = [line.strip() for line in description.splitlines()]
        current_section = ''
        sections = {'': ''}

        for line in lines:
            if header_regex.match(line):
                current_section, seperator, lead = line.partition(':')
                sections[current_section] = lead.strip()
            else:
                sections[current_section] += line + '\n'

        header = getattr(view, 'action', method.lower())
        if header in sections:
            return sections[header].strip()
        if header in self.coerce_method_names:
            if self.coerce_method_names[header] in sections:
                return sections[self.coerce_method_names[header]].strip()
        return sections[''].strip()
コード例 #5
0
    def get_description(self, path, method, view):
        """
        Determine a link description.

        This will be based on the method docstring if one exists,
        or else the class docstring.
        """
        method_name = getattr(view, 'action', method.lower())
        method_docstring = getattr(view, method_name, None).__doc__
        if method_docstring:
            # An explicit docstring on the method or action.
            return formatting.dedent(smart_text(method_docstring))

        description = view.get_view_description()
        lines = [line.strip() for line in description.splitlines()]
        current_section = ''
        sections = {'': ''}

        for line in lines:
            if header_regex.match(line):
                current_section, seperator, lead = line.partition(':')
                sections[current_section] = lead.strip()
            else:
                sections[current_section] += '\n' + line

        header = getattr(view, 'action', method.lower())
        if header in sections:
            return sections[header].strip()
        if header in self.coerce_method_names:
            if self.coerce_method_names[header] in sections:
                return sections[self.coerce_method_names[header]].strip()
        return sections[''].strip()
コード例 #6
0
    def get_notes(self):
        """
        Returns the body of the docstring trimmed before any parameters are
        listed. First, get the class docstring and then get the method's. The
        methods will always inherit the class comments.
        """
        docstring = ""

        class_docs = get_view_description(self.callback)
        class_docs = IntrospectorHelper.strip_yaml_from_docstring(class_docs)
        class_docs = IntrospectorHelper.strip_params_from_docstring(class_docs)
        method_docs = self.get_docs()

        if class_docs is not None:
            docstring += class_docs + "  \n"
        if method_docs is not None:
            method_docs = formatting.dedent(smart_text(method_docs))
            method_docs = IntrospectorHelper.strip_yaml_from_docstring(
                method_docs
            )
            method_docs = IntrospectorHelper.strip_params_from_docstring(
                method_docs
            )
            docstring += '\n' + method_docs
        docstring = docstring.strip()

        return do_markdown(docstring)
コード例 #7
0
    def get_notes(self):
        """
        Returns the body of the docstring trimmed before any parameters are
        listed. First, get the class docstring and then get the method's. The
        methods will always inherit the class comments.
        """
        docstring = ""

        class_docs = self.callback.__doc__ or ''
        class_docs = smart_text(class_docs)
        class_docs = IntrospectorHelper.strip_yaml_from_docstring(class_docs)
        class_docs = IntrospectorHelper.strip_params_from_docstring(class_docs)
        method_docs = self.get_docs()

        if class_docs is not None:
            docstring += class_docs + "  \n"
        if method_docs is not None:
            method_docs = formatting.dedent(smart_text(method_docs))
            method_docs = IntrospectorHelper.strip_yaml_from_docstring(
                method_docs
            )
            method_docs = IntrospectorHelper.strip_params_from_docstring(
                method_docs
            )
            docstring += '\n' + method_docs

        # Markdown is optional
        if apply_markdown:
            docstring = apply_markdown(docstring)
        else:
            docstring = docstring.replace("\n\n", "<br/>")

        return docstring
コード例 #8
0
def get_view_summary(view_cls):
    """Return the viewset's general summary.

    This will extract the paragraphs between the first line and the first
    operation description.

    Example docstring:

        Some operation description here that will not be included.

        This text will be included below the tag.

        This text will also be included.

        create:
        First operation in the docstring which will not be included.


    :param type view_cls: the view class to extra the docstring from.
    """
    try:
        summary = view_cls.__doc__.split("\n\n", 1)[1].split(":", 1)[0]
        if "\n\n" in summary:
            summary = summary.rsplit("\n\n", 1)[0].strip().replace("\r", "")
            return formatting.dedent(smart_str(summary))
    except (AttributeError, IndexError):
        pass

    return ""
コード例 #9
0
def get_view_description(view_cls, html=False, instance=None):
    """
    Given a view class, return a textual description to represent the view.
    This name is used in the browsable API, and in OPTIONS responses.
    This function is the default for the `VIEW_DESCRIPTION_FUNCTION` setting.
    """
    # doc can come from the class or from a detail_route or a list_route method
    documented_object = view_cls
    if instance:
        view_method = get_subroute_method(instance)
        if view_method:
            documented_object = view_method

    description = documented_object.__doc__ or ''
    description = formatting.dedent(smart_text(description))

    if hasattr(documented_object, 'filter_class'):
        default_filter = documented_object.filter_class()
        filters = default_filter.filters
        filters_doc = description_tpl.render(
            Context({
                'filters':
                filters,
                'default_ordering':
                default_filter._default_ordering_field()
            }))
        description += filters_doc

    if html:
        return formatting.markup_description(description)
    return description
コード例 #10
0
def test_docstring_is_not_stripped_by_get_description():
    class ExampleDocstringAPIView(APIView):
        """
        === title

         * item a
           * item a-a
           * item a-b
         * item b

         - item 1
         - item 2

            code block begin
            code
            code
            code
            code block end

        the end
        """
        def get(self, *args, **kwargs):
            pass

        def post(self, request, *args, **kwargs):
            pass

    view = ExampleDocstringAPIView()
    schema = view.schema
    descr = schema.get_description('example', 'get')
    # the first and last character are '\n' correctly removed by get_description
    assert descr == formatting.dedent(ExampleDocstringAPIView.__doc__[1:][:-1])
コード例 #11
0
def get_view_doc(view, html=True):
    """
    Build view documentation. Return in html format.
    If you want in markdown format, use html=False
    """
    try:
        description = view.__doc__ or ''
        description = formatting.dedent(smart_text(description))

        # include filters in description
        filter_fields = get_filter_fields(view)
        if filter_fields:
            filter_doc = ['\n\n\n## Filters', '']
            for f in filter_fields:
                filter_doc.append('- `%s`' % f)
            description += '\n'.join(filter_doc)

        # replace {api_url} by current base url
        api_url = "/api"
        description = description.replace('{api_url}', api_url)
        if html:
            description = formatting.markup_description(description)
        return description
    except:
        import traceback
        traceback.print_exc()
        raise
コード例 #12
0
    def get_notes(self):
        """
        Returns the body of the docstring trimmed before any parameters are
        listed. First, get the class docstring and then get the method's. The
        methods will always inherit the class comments.
        """
        docstring = ""

        class_docs = get_view_description(self.callback)
        class_docs = IntrospectorHelper.strip_yaml_from_docstring(class_docs)
        class_docs = IntrospectorHelper.strip_params_from_docstring(class_docs)
        method_docs = self.get_docs()

        if class_docs is not None:
            docstring += class_docs + "  \n"
        if method_docs is not None:
            method_docs = formatting.dedent(smart_text(method_docs))
            method_docs = IntrospectorHelper.strip_yaml_from_docstring(
                method_docs)
            method_docs = IntrospectorHelper.strip_params_from_docstring(
                method_docs)
            docstring += '\n' + method_docs
        docstring = docstring.strip()

        return do_markdown(docstring)
コード例 #13
0
def test_docstring_is_not_stripped_by_get_description():
    class ExampleDocstringAPIView(APIView):
        """
        === title

         * item a
           * item a-a
           * item a-b
         * item b

         - item 1
         - item 2

            code block begin
            code
            code
            code
            code block end

        the end
        """

        def get(self, *args, **kwargs):
            pass

        def post(self, request, *args, **kwargs):
            pass

    view = ExampleDocstringAPIView()
    schema = view.schema
    descr = schema.get_description('example', 'get')
    # the first and last character are '\n' correctly removed by get_description
    assert descr == formatting.dedent(ExampleDocstringAPIView.__doc__[1:][:-1])
コード例 #14
0
    def get_notes(self):
        """
        Returns the body of the docstring trimmed before any parameters are
        listed. First, get the class docstring and then get the method's. The
        methods will always inherit the class comments.
        """
        docstring = ""

        class_docs = self.callback.__doc__ or ''
        class_docs = smart_text(class_docs)
        class_docs = IntrospectorHelper.strip_yaml_from_docstring(class_docs)
        class_docs = IntrospectorHelper.strip_params_from_docstring(class_docs)
        method_docs = self.get_docs()

        if class_docs is not None:
            docstring += class_docs + "  \n"
        if method_docs is not None:
            method_docs = formatting.dedent(smart_text(method_docs))
            method_docs = IntrospectorHelper.strip_yaml_from_docstring(
                method_docs)
            method_docs = IntrospectorHelper.strip_params_from_docstring(
                method_docs)
            docstring += '\n' + method_docs

        # Markdown is optional
        if apply_markdown:
            docstring = apply_markdown(docstring)
        else:
            docstring = docstring.replace("\n\n", "<br/>")

        return docstring
コード例 #15
0
def amara_get_view_description(view_cls, html=False):
    description = view_cls.__doc__ or ''
    description = formatting.dedent(smart_text(description))
    if not html:
        return description
    return mark_safe('<div class="api-description">{}</div>'.format(
        markup_description(description)))
コード例 #16
0
ファイル: viewsets.py プロジェクト: riahtu/dbservice
 def _extract_schema_data(self, request):
     serializer = self.schema_for()
     model = serializer.opts.model
     # basename = model._meta.object_name.lower()
     modelname = model.__name__
     description = dedent(model.__doc__)
     rw_properties = {}
     ro_properties = {}
     required = []
     for name, field in serializer.get_fields().items():
         # FIXME: need to decide format for specifying JSON Schema for
         # method fields...
         if isinstance(field, SerializerMethodField):
             continue
         if getattr(field, 'required', False):
             required.append(name)
         data = {}
         data['description'] = getattr(field, 'help_text', '')
         data['type'] = self._schema_type_for(field)
         if isinstance(field, ChoiceField):
             # RelatedField also provides choices; don't enumerate those...
             data['enum'] = [
                 stored for stored, presentation in field.choices
             ]
         if getattr(field, 'max_length', None) is not None:
             data['maxLength'] = field.max_length
         if getattr(field, 'min_length', None) is not None:
             data['minLength'] = field.min_length
         if isinstance(field, DateTimeField):
             data['format'] = 'date-time'
         if isinstance(field, EmailField):
             data['format'] = 'email'
         if isinstance(field, PrimaryKeyRelatedField):
             opts = field.queryset.model._meta
             rel_basename = '{}-{}'.format(opts.app_label,
                                           opts.object_name.lower())
             rel_href = reverse('{}-list'.format(rel_basename),
                                request=request) + '{$}/'
             rel_targetschema = reverse(
                 'schema-{}-detail'.format(rel_basename), request=request)
             data['links'] = [{
                 'rel': 'full',
                 'href': rel_href,
                 'targetSchema': {
                     '$ref': rel_targetschema,
                 }
             }]
         if field.read_only:
             data['readOnly'] = True
             ro_properties[name] = data
         else:
             rw_properties[name] = data
     return {
         'modelname': modelname,
         'description': description,
         'rw_properties': rw_properties,
         'ro_properties': ro_properties,
         'required': required,
     }
コード例 #17
0
ファイル: doc_settings.py プロジェクト: kznmft/penn-clubs
 def parse_docstring(cls, docstring):
     docstring = dedent(docstring)
     match = cls.META_REGEX.search(docstring)
     if match is not None:
         meta = yaml.safe_load(match.group(1))
         docstring = cls.META_REGEX.sub("", docstring).strip()
     else:
         meta = None
     return docstring, meta
コード例 #18
0
def get_restructuredtext(view_cls, html=False):
    from docutils import core
    description = view_cls.__doc__ or ''
    description = formatting.dedent(smart_text(description))
    if html:
        parts = core.publish_parts(source=description, writer_name='html')
        html = parts['body_pre_docinfo'] + parts['fragment']
        return mark_safe(html)
    return description
コード例 #19
0
ファイル: base.py プロジェクト: Darriall/editorsnotes
 def get_view_description(self, html=False):
     description = self.__doc__ or """
     Returns a nested list of objects that would be also be deleted when
     this object is deleted.
     """
     description = formatting.dedent(description)
     if html:
         return formatting.markup_description(description)
     return description
コード例 #20
0
def get_restructuredtext(view_cls, html=False):
    from docutils import core
    description = view_cls.__doc__ or ''
    description = formatting.dedent(smart_text(description))
    if html:
        parts = core.publish_parts(source=description, writer_name='html')
        html = parts['body_pre_docinfo'] + parts['fragment']
        return mark_safe(html)
    return description
コード例 #21
0
ファイル: base.py プロジェクト: Darriall/editorsnotes
 def get_view_description(self, html=False):
     description = self.__doc__ or """
     Returns a nested list of objects that would be also be deleted when
     this object is deleted.
     """
     description = formatting.dedent(description)
     if html:
         return formatting.markup_description(description)
     return description
コード例 #22
0
 def _get_yaml_docstring(self, method: str, docstring: str,
                         **many: Dict[str, bool]) -> list:
     """
     Parse Docstring formatted in YAML notation
     :param method: View method
     :param docstring: The Docstring from method or from class
     :param many: Pass <property=True> to append/update existing data, else overwrite
     :return: List of properties from YAML-formatted Docstring
     """
     method = "get" if method == "list" else method
     # Invalid properties will be ignored
     valid_properties = ("summary", "description", "tags", "responses", 200,
                         201, 202, 204, 400, 401, 403, 404, 500, 502, 503)
     # Create valid properties many dict (False: overwrite, True: append/update)
     for valid_property in valid_properties:
         many.setdefault(valid_property, False)
     # Same checks got from .get_descriptions()
     coerce_method_names = api_settings.SCHEMA_COERCE_METHOD_NAMES
     if method in coerce_method_names:
         method = coerce_method_names[method]
     docstring_for_yaml = self._yaml_safe_clean(docstring)
     try:
         # Load YAML
         yml = yaml.load(docstring_for_yaml, Loader=yaml.SafeLoader)
     except ScannerError:
         # Invalid YAML, let's store the string in description key
         return [{
             "key":
             "description",
             "value":
             "" + "\n".join(
                 line.strip()
                 for line in formatting.dedent(docstring).splitlines()),
             "append":
             many["description"]
         }]
     result = yml
     # None YAML, let's return and empty description
     if yml is None:
         return [{
             "key": "description",
             "value": "",
             "append": many["description"]
         }]
     # Method doesn't exist in yml
     if method not in yml:
         result = {method: yml}
     # Method property value is str
     if isinstance(result[method], str):
         result = {method: {"description": result[method]}}
     # Return valid property
     return [{
         "key": k,
         "value": v.strip() if isinstance(v, str) else v,
         "append": many[k]
     } for k, v in result[method].items() if k in valid_properties]
コード例 #23
0
 def get_view_description(self, obj, attr='__doc__', html=False):
     """
     Get the doc string from either cls or function, parse it and return
     """
     description = getattr(obj, attr,
                           "No description provided by developer")
     description = formatting.dedent(smart_text(description))
     if html:
         return formatting.markup_description(description)
     return description
コード例 #24
0
ファイル: views.py プロジェクト: yeloo0320/lvyou
def get_view_description(view_cls, html=False):
    """
    Given a view class, return a textual description to represent the view.
    This name is used in the browsable API, and in OPTIONS responses.
    This function is the default for the `VIEW_DESCRIPTION_FUNCTION` setting.
    """
    description = view_cls.__doc__ or ''
    description = formatting.dedent(smart_text(description))
    if html:
        return formatting.markup_description(description)
    return description
コード例 #25
0
 def get_description(self, view, status_code):
     try:
         description = getattr(view, view.action).__doc__ or ''
         description = formatting.dedent(
             smart_text(description)).split('---')
         description = description[0] if isinstance(description,
                                                    list) else description
         return formatting.markup_description(description)
     except (AttributeError, TypeError):
         return super(ShoutitBrowsableAPIRenderer,
                      self).get_description(view, status_code)
コード例 #26
0
    def get_paths(self, top, components, request, public):
        """
        Generate the Swagger Paths for the API from the given endpoints.
        """
        if not top:
            return None

        ret=[]
        # import pdb; pdb.set_trace()
        for category in top:
            # print('~~~~~~~~~')

            endpoints=category['points']
            if endpoints is None or len(endpoints)==0:
                continue
            prefix = self.get_path(category['prefix'])
            if prefix.endswith("/"):
                prefix=prefix[0:-1]
            assert '{' not in prefix, "base path cannot be templated in swagger 2.0"

            paths = {}
            for path, (view_cls, methods) in sorted(endpoints.items()):
                _path={}
                #print(path)
                for method, view in methods:
                    # print(method)
                    # if not self.should_include_endpoint(path, method, view, public):
                    #     continue
                    method_lower=method.lower()
                    method_name = getattr(view, 'action', method_lower)
                    method_docstring = getattr(view, method_name, None).__doc__
                    if method_docstring:
                        method_docstring = self._get_description_section(view, method.lower(),
                                                                         formatting.dedent(smart_text(method_docstring)))
                    else:
                        method_docstring = self._get_description_section(view, getattr(view, 'action', method.lower()),
                                                                         view.get_view_description())
                    if not method_docstring:
                        method_docstring = "_"

                    (_name, _desc) = self.split_summary_from_description(method_docstring)
                    if _name is None:
                        _name = _desc
                    _path[method_lower]={"name": _name, "description": _desc}

                path_suffix = path[len(prefix):]
                if not path_suffix.startswith('/'):
                    path_suffix = '/' + path_suffix
                paths[path_suffix]=_path
            if not paths is None:
                ret.append({"basePath":prefix,"basePathArray":prefix.strip("/").split("/"),"paths":paths})
        #print(ret)
        return ret
コード例 #27
0
 def create_yaml_object(self, docstring):
     """Create YAML object from docstring"""
     base, yaml_string = self.split_docstring(docstring)
     if not yaml_string:
         return None
     yaml_string = formatting.dedent(yaml_string)
     try:
         # Note that it's not `safe_load`. But docstrings shouldn't really
         # have unsafe values, right?..
         return yaml.load(yaml_string)
     except yaml.YAMLError:  # TODO: log?..
         return None
コード例 #28
0
ファイル: views.py プロジェクト: fengsi/django-rest-framework
def get_view_description(view_cls, html=False):
    """
    Given a view class, return a textual description to represent the view.
    This name is used in the browsable API, and in OPTIONS responses.

    This function is the default for the `VIEW_DESCRIPTION_FUNCTION` setting.
    """
    description = view_cls.__doc__ or ''
    description = formatting.dedent(smart_text(description))
    if html:
        return formatting.markup_description(description)
    return description
コード例 #29
0
 def format_docstring(self, view, method, docstring):
     macros = settings.BROWSABLE_DOCUMENT_MACROS
     if view:
         macros['FILTERS'] = get_filters(view)
         if '%(SERIALIZER)s' in docstring:
             macros['SERIALIZER'] = get_serializer(view, include_read_only=True)
         if '%(WRITABLE_SERIALIZER)s' in docstring:
             macros['WRITABLE_SERIALIZER'] = get_serializer(view, include_read_only=False)
     string = formatting.dedent(docstring)
     formatted = string % macros
     formatted = self.substitute_urls(view, method, formatted)
     string = smart_text(formatted)
     return formatting.markup_description(string)
コード例 #30
0
 def create_yaml_object(self, docstring):
     """Create YAML object from docstring"""
     docstring = trim_docstring(docstring)
     p = re.compile('^|\n{}'.format(YAMLDocstringParser.SPLITTER))
     splitted = p.split(docstring)
     if len(splitted) < 2:
         return None
     yaml_string = splitted[1]
     yaml_string = formatting.dedent(yaml_string)
     try:
         return yaml.load(yaml_string)
     except yaml.YAMLError as e:
         return None
コード例 #31
0
    def load_obj_from_docstring(self, docstring):
        """Loads YAML from docstring"""

        # update one dict by other recursively
        def recursive_update(obj, other):
            for key, value in other.iteritems():
                if key in obj and key != 'overwrite':
                    # if value is dictionary we need to update it
                    if isinstance(value,
                                  dict) and not value.get('overwrite', False):
                        recursive_update(obj[key], other[key])
                    # if value is a list we need to extend it
                    elif isinstance(value, list):
                        obj[key].extend(value)
                    else:
                        obj[key] = value
                else:
                    obj[key] = value

        if not docstring:
            return {}

        split_lines = trim_docstring(docstring).split('\n')

        # Cut YAML from rest of docstring
        for index, line in enumerate(split_lines):
            line = line.strip()
            if line.startswith('---'):
                cut_from = index
                break
        else:
            return {}
        yaml_string = formatting.dedent("\n".join(split_lines[cut_from:]))

        try:
            yaml_obj = yaml.load(yaml_string)
            # if is parent view specified, we need to get docs from parent view
            if 'inherit_docs_from' in yaml_obj:
                parent_class = self._load_class(
                    yaml_obj['inherit_docs_from'],
                    self.method_introspector.callback)
                parent_docs = self.method_introspector.get_inherited_docs(
                    parent_class)
                parent_obj = self.load_obj_from_docstring(
                    docstring=parent_docs)
                recursive_update(parent_obj, yaml_obj)
                yaml_obj = parent_obj
        except yaml.YAMLError as e:
            self.yaml_error = e
            return {}
        return yaml_obj
コード例 #32
0
    def get_metadata_content_tuple(self):
        """Tries to load the frontmatter data and content for the current action type for the operation
        """
        view_docs = formatting.dedent(self.view.__doc__)

        docs = list(map(lambda x: f'---{x}', view_docs.split('===')[1:]))
        method = self.method
        action = getattr(self.view, 'action_map', {}).get(method.lower(), None) if self.view.action_map else None
        for doc_bloc in docs:
            metadata, content = frontmatter.parse(doc_bloc)
            if not metadata:
                continue
            action_to_map = metadata.get('action', 'default')
            if action_to_map == action or (isinstance(action_to_map, list) and action in action_to_map):
                return metadata, content
        if action and hasattr(self.view, action):
            action_func = getattr(self.view, action, None)
            action_docs = formatting.dedent(action_func.__doc__)
            if '===' in action_docs:
                metadata, content = frontmatter.parse(action_docs.replace('===', '---'))
                return metadata, content
            return None, action_docs
        return None, view_docs
コード例 #33
0
ファイル: apiv2_utils.py プロジェクト: xavierfav/freesound
def get_view_description(cls, html=False):
    description = ''
    if getattr(cls, 'get_description', None):
        cache_key = cls.__name__
        cached_description = cache.get(cache_key)
        if not cached_description:
            description = cls.get_description()
            description = formatting.dedent(smart_text(description))
            # Cache for 1 hour (if we update description, it will take 1 hour to show)
            cache.set(cache_key, description, 60 * 60)
        else:
            description = cached_description
    if html:
        return formatting.markup_description(description)
    return description
コード例 #34
0
ファイル: renderers.py プロジェクト: miphreal/drf-tweaks
def get_view_description(view_cls, html=False):
    from django_markwhat.templatetags.markup import restructuredtext
    description = view_cls.__doc__ or ''
    description = formatting.dedent(smart_text(description))
    if html:
        rst_doc = getattr(view_cls, 'rst_doc', None)
        if rst_doc:
            if isinstance(rst_doc, str):
                path = os.path.dirname(sys.modules[view_cls.__module__].__file__)
                path = os.path.join(path, rst_doc)
                with open(path) as rst:
                    return restructuredtext(rst.read())
            return restructuredtext(description)
        return formatting.markup_description(description)
    return description
コード例 #35
0
    def get_summary(self, path, method):
        """
        Determine a path summary.

        This will be based on the method docstring if one exists.
        """
        view = self.view

        method_name = getattr(view, 'action', method.lower())
        method_docstring = getattr(view, method_name, None).__doc__
        if method_docstring:
            # An explicit docstring on the method or action.
            return self._get_summary_section(
                view, method.lower(),
                formatting.dedent(smart_str(method_docstring)))
コード例 #36
0
ファイル: apiv2_utils.py プロジェクト: MTG/freesound
def get_view_description(cls, html=False):
    description = ''
    if getattr(cls, 'get_description', None):
        cache_key = cls.__name__
        cached_description = cache.get(cache_key)
        if not cached_description:
            description = cls.get_description()
            description = formatting.dedent(smart_text(description))
            # Cache for 1 hour (if we update description, it will take 1 hour to show)
            cache.set(cache_key, description, 60*60)
        else:
            description = cached_description
    if html:
        return formatting.markup_description(description)
    return description
コード例 #37
0
    def get_description(self, path, method):
        """
        Determine a link description.

        This will be based on the method docstring if one exists,
        or else the class docstring.
        """
        view = self.view

        method_name = getattr(view, 'action', method.lower())
        method_docstring = getattr(view, method_name, None).__doc__
        if method_docstring:
            # An explicit docstring on the method or action.
            return self._get_description_section(view, method.lower(), formatting.dedent(smart_text(method_docstring)))
        else:
            return self._get_description_section(view, getattr(view, 'action', method.lower()), view.get_view_description())
コード例 #38
0
def _get_type_from_docstring(value, default=None):
    """
    Convert docstring into object suitable for inclusion as documentation. It
    tries to parse the docstring as JSON, falling back on provided default
    value.
    """
    if value:
        try:
            return json.loads(value)
        except ValueError:
            return formatting.dedent(str(value))

    if default is not None:
        return default

    return None
コード例 #39
0
ファイル: views.py プロジェクト: 2509934810/studyPython
def get_view_description(view, html=False):
    """
    Given a view instance, return a textual description to represent the view.
    This name is used in the browsable API, and in OPTIONS responses.

    This function is the default for the `VIEW_DESCRIPTION_FUNCTION` setting.
    """
    # Description may be set by some Views, such as a ViewSet.
    description = getattr(view, 'description', None)
    if description is None:
        description = view.__class__.__doc__ or ''

    description = formatting.dedent(smart_str(description))
    if html:
        return formatting.markup_description(description)
    return description
コード例 #40
0
    def get_description(self, path, method):
        """
        Determine a link description.

        This will be based on the method docstring if one exists,
        or else the class docstring.
        """
        view = self.view

        method_name = getattr(view, 'action', method.lower())
        method_docstring = getattr(view, method_name, None).__doc__
        if method_docstring:
            # An explicit docstring on the method or action.
            return self._get_description_section(view, method.lower(), formatting.dedent(smart_text(method_docstring)))
        else:
            return self._get_description_section(view, getattr(view, 'action', method.lower()), view.get_view_description())
コード例 #41
0
ファイル: views.py プロジェクト: jplaut/django-rest-framework
def get_view_description(view, html=False):
    """
    Given a view class, return a textual description to represent the view.
    This name is used in the browsable API, and in OPTIONS responses.

    This function is the default for the `VIEW_DESCRIPTION_FUNCTION` setting.
    """
    # Description may be set by some Views, such as a ViewSet.
    description = getattr(view, 'description', None)
    if description is None:
        description = view.__class__.__doc__ or ''

    description = formatting.dedent(smart_text(description))
    if html:
        return formatting.markup_description(description)
    return description
コード例 #42
0
ファイル: views.py プロジェクト: cedadev/jasmin-cloud
def get_view_description(view_cls, html=False):
    """
    Alternative django-rest-framework ``VIEW_DESCRIPTION_FUNCTION`` that allows
    RestructuredText to be used instead of Markdown.

    This allows docstrings to be used in the DRF-generated HTML views and in
    Sphinx-generated API views.
    """
    description = view_cls.__doc__ or ''
    description = formatting.dedent(smart_text(description))
    if html:
        # Get just the HTML parts corresponding to the docstring
        parts = core.publish_parts(source=description, writer_name='html')
        html = parts['body_pre_docinfo'] + parts['fragment']
        # Mark the output as safe for rendering as-is
        return mark_safe(html)
    return description
コード例 #43
0
    def load_obj_from_docstring(self, docstring):
        """Loads YAML from docstring"""

        # update one dict by other recursively
        def recursive_update(obj, other):
            for key, value in other.iteritems():
                if key in obj and key != 'overwrite':
                    # if value is dictionary we need to update it
                    if isinstance(value, dict) and not value.get('overwrite', False):
                        recursive_update(obj[key], other[key])
                    # if value is a list we need to extend it
                    elif isinstance(value, list):
                        obj[key].extend(value)
                    else:
                        obj[key] = value
                else:
                    obj[key] = value

        if not docstring:
            return {}

        split_lines = trim_docstring(docstring).split('\n')

        # Cut YAML from rest of docstring
        for index, line in enumerate(split_lines):
            line = line.strip()
            if line.startswith('---'):
                cut_from = index
                break
        else:
            return {}
        yaml_string = formatting.dedent("\n".join(split_lines[cut_from:]))

        try:
            yaml_obj = yaml.load(yaml_string)
            # if is parent view specified, we need to get docs from parent view
            if 'inherit_docs_from' in yaml_obj:
                parent_class = self._load_class(yaml_obj['inherit_docs_from'], self.method_introspector.callback)
                parent_docs = self.method_introspector.get_inherited_docs(parent_class)
                parent_obj = self.load_obj_from_docstring(docstring=parent_docs)
                recursive_update(parent_obj, yaml_obj)
                yaml_obj = parent_obj
        except yaml.YAMLError as e:
            self.yaml_error = e
            return {}
        return yaml_obj
コード例 #44
0
def get_googledocstring(view_cls, html=False):
    """Parses a docstring containing Google-style docs into HTML.

    This uses the Napoleon Sphinx extension to parse Google-style argument
    docstrings into reStructuredText, then convert these into HTML for
    django-rest-swagger.
    """
    from docutils import core

    description = view_cls.__doc__ or ''
    config = Config(napoleon_use_param=False, napoleon_use_rtype=False)
    description = GoogleDocstring(description, config=config)
    description = formatting.dedent(smart_text(description))
    if html:
        parts = core.publish_parts(source=description, writer_name='html')
        html = parts['body_pre_docinfo'] + parts['fragment']
        return mark_safe(html)
    return description
コード例 #45
0
    def get_description(self):
        """
        Returns the body of the docstring trimmed before any parameters are
        listed. First, get the class docstring and then get the method's. The
        methods will always inherit the class comments.
        """
        class_docs = self._clean_docs(get_view_description(self.callback))
        method_docs = self._clean_docs(formatting.dedent(smart_text(self.get_docs())))

        if self.yaml_parser.get_param('replace_docs', False):
            docstring = method_docs
        else:
            docstring = "\n\n".join(filter(None, [class_docs, method_docs]))

        explicit_docs = self.yaml_parser.get_param("docs", None)
        if explicit_docs is not None:
            docstring = explicit_docs.format(super=docstring)

        return docstring.strip()
コード例 #46
0
    def load_obj_from_docstring(self, docstring):
        """Loads YAML from docstring"""
        split_lines = trim_docstring(docstring).split('\n')

        # Cut YAML from rest of docstring
        for index, line in enumerate(split_lines):
            line = line.strip()
            if line.startswith('---'):
                cut_from = index
                break
        else:
            return None

        yaml_string = "\n".join(split_lines[cut_from:])
        yaml_string = formatting.dedent(yaml_string)
        try:
            return yaml.load(yaml_string)
        except yaml.YAMLError as e:
            self.yaml_error = e
            return None
コード例 #47
0
 def format_docstring(self, view, method, docstring):
     macros = settings.BROWSABLE_DOCUMENT_MACROS
     if view:
         macros['FILTERS'] = get_filters(view)
         if 'list' == method:
             ordering_field = get_ordering_field(view, method)
             if ordering_field:
                 ordering_string = ORDERING_STRING + " %s ." % ordering_field
                 macros['FILTERS'] += ordering_string
         if '%(SERIALIZER)s' in docstring:
             macros['SERIALIZER'] = get_serializer(view, include_read_only=True)
         if '%(WRITABLE_SERIALIZER)s' in docstring:
             macros['WRITABLE_SERIALIZER'] = get_serializer(view, include_read_only=False)
         if hasattr(view, 'docstring_macros'):
             macros.update(view.docstring_macros)
     string = formatting.dedent(docstring)
     formatted = string % macros
     formatted = self.substitute_urls(view, method, formatted)
     string = smart_text(formatted)
     return formatting.markup_description(string)
コード例 #48
0
    def test_renders_default_schema_with_custom_title_url_and_description(self):
        expected_out = """info:
                            description: Sample description
                            title: SampleAPI
                            version: ''
                          openapi: 3.0.0
                          paths:
                            /:
                              get:
                                operationId: list
                          servers:
                          - url: http://api.sample.com/
                          """
        call_command('generateschema',
                     '--title=SampleAPI',
                     '--url=http://api.sample.com',
                     '--description=Sample description',
                     stdout=self.out)

        self.assertIn(formatting.dedent(expected_out), self.out.getvalue())
コード例 #49
0
ファイル: drf.py プロジェクト: hds-lab/coding-ml
def get_view_description(view_cls, html=False):
    """
    Alternative view description function to be used as the DRF
    ``VIEW_DESCRIPTION_FUNCTION`` so that RestructuredText can be used
    instead of the DRF-default MarkDown.
 
    Except for the RST parts, derived by [email protected] from the
    DRF default get_view_description function.
    """

    description = view_cls.__doc__ or ''
    description = formatting.dedent(force_bytes_or_smart_bytes(description))
    if html:
        # from https://wiki.python.org/moin/ReStructuredText -- we use the
        # third recipe to get just the HTML parts corresponding to the ReST
        # docstring:
        parts = core.publish_parts(source=description, writer_name='html')
        html = parts['body_pre_docinfo']+parts['fragment']
        # have to use mark_safe so our HTML will get explicitly marked as
        # safe and will be correctly rendered
        return mark_safe(html)

    return description
コード例 #50
0
    def get_description(self, path, method):
        """
        Determine a link description.

        This will be based on the method docstring if one exists,
        or else the class docstring.
        """
        view = self.view

        method_name = getattr(view, 'action', method.lower())
        method_docstring = getattr(view, method_name, None).__doc__
        if method_docstring:
            # An explicit docstring on the method or action.
            return formatting.dedent(smart_text(method_docstring))

        description = view.get_view_description()
        lines = [line for line in description.splitlines()]
        current_section = ''
        sections = {'': ''}

        for line in lines:
            if header_regex.match(line):
                current_section, seperator, lead = line.partition(':')
                sections[current_section] = lead.strip()
            else:
                sections[current_section] += '\n' + line

        # TODO: SCHEMA_COERCE_METHOD_NAMES appears here and in `SchemaGenerator.get_keys`
        coerce_method_names = api_settings.SCHEMA_COERCE_METHOD_NAMES
        header = getattr(view, 'action', method.lower())
        if header in sections:
            return sections[header].strip()
        if header in coerce_method_names:
            if coerce_method_names[header] in sections:
                return sections[coerce_method_names[header]].strip()
        return sections[''].strip()
コード例 #51
0
 def format_docstring(self, docstring):
     formatted = docstring % settings.BROWSABLE_DOCUMENT_MACROS
     string = formatting.dedent(smart_text(formatted))
     return formatting.markup_description(string)
コード例 #52
0
 def get_content(self, view_cls, html=True, request=None):
     return dedent(view_cls.__doc__ or "")
コード例 #53
0
def test_dedent_tabs():
    result = 'first string\n\nsecond string'
    assert dedent("    first string\n\n    second string") == result
    assert dedent("first string\n\n    second string") == result
    assert dedent("\tfirst string\n\n\tsecond string") == result
    assert dedent("first string\n\n\tsecond string") == result
コード例 #54
0
def test_dedent_tabs():
    assert dedent("\tfirst string\n\n\tsecond string") == "first string\n\n\tsecond string"
コード例 #55
0
ファイル: views.py プロジェクト: Bazzinga/django_rest_learn
def get_view_description(cls, html=False):
    description = cls.__doc__ or ''
    description = formatting.dedent(smart_text(description))
    if html:
        return formatting.markup_description(description)
    return description