Esempio n. 1
0
def describe_handler(handler):
    """Return a serialisable description of a handler.

    :type handler: :class:`OperationsHandler` or
        :class:`AnonymousOperationsHandler` instance or subclass.
    """
    # Want the class, not an instance.
    if isinstance(handler, BaseHandler):
        handler = type(handler)

    path = generate_doc(handler).resource_uri_template
    path = "" if path is None else path

    resource_uri = getattr(handler, "resource_uri", lambda: ())
    view_name, uri_params, uri_kw = merge(resource_uri(), (None, (), {}))
    assert uri_kw == {}, (
        "Resource URI specifications with keyword parameters are not yet "
        "supported: handler=%r; view_name=%r" % (handler, view_name))

    return {
        "actions": list(describe_actions(handler)),
        "doc": getdoc(handler),
        "name": handler.__name__,
        "params": tuple(uri_params),
        "path": path,
        }
Esempio n. 2
0
    def test_resource_uri_in_docs_matches_handlers_idea_of_resource_uri(self):
        # Sigh. Piston asks handlers for resource_uri information, but also
        # makes use of Django's URL patterns to figure out resource_uri
        # templates for the documentation. Here we check that they match up.
        formatter = string.Formatter()

        def gen_handlers(resource):
            if resource.anonymous is not None:
                yield resource.anonymous
            if resource.handler is not None:
                yield resource.handler

        handlers = chain.from_iterable(
            map(gen_handlers, find_api_resources(urlconf))
        )

        mismatches = []

        for handler in map(type, handlers):
            if hasattr(handler, "resource_uri"):
                resource_uri_params = handler.resource_uri()[1]
                resource_uri_template = generate_doc(
                    handler
                ).resource_uri_template

                fields_expected = tuple(resource_uri_params)
                fields_observed = tuple(
                    fname
                    for _, fname, _, _ in formatter.parse(
                        resource_uri_template
                    )
                    if fname is not None
                )

                if fields_observed != fields_expected:
                    mismatches.append(
                        (handler, fields_expected, fields_observed)
                    )

        if len(mismatches) != 0:
            messages = (
                "{handler.__module__}.{handler.__name__} has mismatched "
                "fields:\n  expected: {expected}\n  observed: {observed}"
                "".format(
                    handler=handler,
                    expected=" ".join(expected),
                    observed=" ".join(observed),
                )
                for handler, expected, observed in mismatches
            )
            messages = chain(
                messages,
                [
                    "Amend the URL patterns for these handlers/resources so that "
                    "the observed fields match what is expected."
                ],
            )
            self.fail("\n--\n".join(messages))
Esempio n. 3
0
File: doc.py Progetto: zhangrb/maas
def generate_api_docs(resources):
    """Generate ReST documentation objects for the ReST API.

    Yields Piston Documentation objects describing the given resources.

    This also ensures that handlers define 'resource_uri' methods. This is
    easily forgotten and essential in order to generate proper documentation.

    :return: Generates :class:`piston.doc.HandlerDocumentation` instances.
    """
    sentinel = object()
    resource_key = (lambda resource: resource.handler.__class__.__name__)
    for resource in sorted(resources, key=resource_key):
        handler = type(resource.handler)
        if getattr(handler, "resource_uri", sentinel) is sentinel:
            raise AssertionError("Missing resource_uri in %s" %
                                 handler.__name__)
        yield generate_doc(handler)