Beispiel #1
0
    def testUsageRequestPayloadMandatory1(self):
        # f = HTTPTopLevel('users', 'PUT')
        usage = HTTPUsage('/dummy', 'Bee-bop')
        payload = Payload()
        usage.addRequestPayload(payload)

        field = PayloadField('f1', 'type', 'desc', mandatory=False)
        payload.addField(field)
        self.assertFalse(usage.requestPayloadMandatory())

        field = PayloadField('f2', 'type', 'desc', mandatory=True)
        payload.addField(field)
        self.assertTrue(usage.requestPayloadMandatory())
Beispiel #2
0
 def TestUsageExamples(self):
     """
     Rather un-exciting test but at least the code is exercised and expected
     behaviour checked.
     """
     u = HTTPUsage('/dummy', 'an example of great profundity')
     request = 'foo'
     response = 'bar'
     description = 'baz'
     example = HTTPExample(request, response, description)
     u.addExample(example)
     self.assertEqual(1, len(u.examples))
     self.assertEqual('foo', u.examples[0].request)
     self.assertEqual('bar', u.examples[0].response)
     self.assertEqual('baz', u.examples[0].description)
Beispiel #3
0
    def testUsageRequestPayloadMandatory2(self):
        # f = HTTPTopLevel('users', 'PUT')
        usage = HTTPUsage('/dummy', 'Bee-bop')

        payload = Payload()
        usage.addRequestPayload(payload)
        field = PayloadField('f1', 'type', 'desc', mandatory=False)
        payload.addField(field)

        payload = Payload()
        payload.format = 'blah'
        usage.addRequestPayload(payload)
        field = PayloadField('f1', 'type', 'desc', mandatory=False)
        payload.addField(field)

        self.assertFalse(usage.requestPayloadMandatory())

        payload = JSONPayload()
        usage.addRequestPayload(payload)
        field = PayloadField('f1', 'type', 'desc', mandatory=True)
        payload.addField(field)

        self.assertTrue(usage.requestPayloadMandatory())
Beispiel #4
0
 def testNotes(self):
     f = HTTPTopLevel('users', 'PUT')
     usage = HTTPUsage('/dummy', 'an example of great profundity')
     f.addUsage(usage)
     note = Note('hey')
     usage.addNote(note)
     note = Note('hey')
     usage.addNote(note)
     self.assertEqual(len(usage.notes), 2)
     self.reg.register(f)
     apis = self.reg.get('users', 'PUT')
     self.assertEqual(apis, [['users', [('PUT', f)]]])
     f = apis[0][1][0][1]
     self.assertEqual(len(f.usages), 1)
     self.assertEqual(len(f.usages[0].notes), 2)
Beispiel #5
0
    def testFindUsage(self):

        class Dummy1(object):
            pass

        class Dummy2(object):
            pass

        class Dummy3(object):
            pass

        f = HTTPTopLevel('users', 'PUT')
        self.reg.register(f)
        usage1 = HTTPUsage('', "Return a list of all users.")
        usage1.resourceClass = Dummy1
        f.addUsage(usage1)

        f = HTTPTopLevel('dummy', 'GET')
        self.reg.register(f)
        usage2 = HTTPUsage('', "Return a list of all dummies.")
        usage2.resourceClass = Dummy2
        f.addUsage(usage2)

        # Find the usage with class Dummy1.
        u = self.reg.findUsage('users', 'PUT',
                               usageResourceClass=Dummy1)
        self.assertTrue(u.resourceClass is usage1.resourceClass)

        # Find the usage with class Dummy2.
        u = self.reg.findUsage('dummy', 'GET',
                               usageResourceClass=Dummy2)
        self.assertTrue(u.resourceClass is usage2.resourceClass)

        # Ask for a non-existent usage class.
        self.assertRaises(error.NoSuchUsage,
                          self.reg.findUsage, 'dummy', 'GET',
                          usageResourceClass=Dummy3)

        # Ask for a non-existent toplevel.
        self.assertRaises(error.NoSuchToplevel,
                          self.reg.findUsage, 'sunny', 'PUT',
                          usageResourceClass=Dummy2)

        # Ask for a non-existent verb.
        self.assertRaises(error.NoSuchVerb,
                          self.reg.findUsage, 'dummy', 'PUT',
                          usageResourceClass=Dummy2)
Beispiel #6
0
    def deferred_render_DELETE(self, request):
        usage = registry.findUsage(httpTagCategoryName, 'DELETE', TagsResource)
        registry.checkRequest(usage, request)
        yield self.facadeClient.deleteTag(self.session,
                                          sep.join(request.postpath))
        request.setResponseCode(usage.successCode)


# ------------------------------ Tags POST --------------------------
topLevel = HTTPTopLevel(httpTagCategoryName, 'POST')
registry.register(topLevel)

# --- POST /tags/NAMESPACE1/NAMESPACE2 ------------------------

usage = HTTPUsage(
    apiDoc.NS_NS, 'Add a tag name to a namespace.  Intermediate namespaces '
    "are created automatically if they don't already exist.")
topLevel.addUsage(usage)
usage.resourceClass = TagsResource
usage.successCode = http.CREATED

requestPayload = JSONPayload()
requestPayload.addField(
    PayloadField('name', unicode, 'The name of the new tag.'))
requestPayload.addField(
    PayloadField('description',
                 unicode,
                 'A description of the tag.',
                 mayBeNone=True))
requestPayload.addField(
    PayloadField('indexed', bool,
Beispiel #7
0
                return AboutObjectResource(self.facadeClient, self.session,
                                           about)


# ------------------------------ About POST -----------------------------
topLevel = HTTPTopLevel(httpAboutCategoryName, 'POST')
topLevel.description = "Create a new object."
registry.register(topLevel)

# --- POST /about -------------------------------------------------------

usage = HTTPUsage('/' + apiDoc.ABOUTSTR, ('''Create a new object with the
    given about value. If there is already a Fluidinfo object whose
    ''' + apiDoc.ABOUT_TAG + ''' tag has the given value, the returned
    object id will be that of the pre-existing object. In this call, and
    all others with an about value in the URI, you must convert
    your about value to UTF-8 and then
    <a href="http://en.wikipedia.org/wiki/Percent-encoding">
    percent-encode</a> it before adding it to the request URI. You must
    provide valid credentials for this call to succeed.
    For an example see the PUT request, below.'''))

topLevel.addUsage(usage)
usage.resourceClass = AboutObjectResource
usage.successCode = http.CREATED

usage.addReturn(
    Return(apiDoc.BAD_REQUEST,
           'The ' + apiDoc.ABOUTSTR + ' argument was not valid UTF-8.'))

apiDoc.addBadRequestPayload(usage)
Beispiel #8
0
        request.setHeader('Content-type', 'application/json')
        request.setResponseCode(http.OK)
        returnValue(body)

# API DOCUMENTATION

# GET on  /recent
topLevel = HTTPTopLevel('recent', 'GET')
topLevel.description = dedent("""
    The GET method on recent is used to retrieve information about the latest
    updated tag values on a given object or user.""")
registry.register(topLevel)

# GET on /recent/objects
usage = HTTPUsage('/objects', dedent("""
    To request information on the latest tag values on the objects returned by
    a given query"""))
usage.resourceClass = RecentObjectsActivityResource
usage.addArgument(Argument(
    'query',
    dedent("""
    A query string specifying what sorts of objects to get recent activity for.
    The query language is described <a
    href="http://doc.fluidinfo.com/fluidDB/queries.html">here</a>. You must
    convert your query to UTF-8 and then <a href="http://en.wikipedia.org/wiki
    /Percent-encoding">
     percent-encode</a> it before adding it to the request URI
     """),
    'string',
    default=None,
    mandatory=True))
Beispiel #9
0
        body = payloads.buildPayload(responseType, responseDict)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setHeader('Location', location)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)


# ------------------------------ Users POST -------------------------------
topLevel = HTTPTopLevel(httpUserCategoryName, 'POST')
topLevel.adminOnly = True
registry.register(topLevel)

# --- POST /users ---------------------------------------------------------

usage = HTTPUsage('', 'Create a new user.')
usage.adminOnly = True
usage.resourceClass = UsersResource
usage.successCode = http.CREATED
topLevel.addUsage(usage)

apiDoc.addNeedAdmin(usage, apiDoc.CREATE)

usage.addReturn(Return(
    apiDoc.PRECONDITION_FAILED,
    'If the user already exists.'))

usage.addReturn(Return(
    apiDoc.BAD_REQUEST,
    """If the username is unacceptable due to syntax. Usernames may
    contain only letters (according to the Unicode standard), digits,
Beispiel #10
0
# ------------------------------ Values GET -----------------------------
topLevel = HTTPTopLevel(httpValueCategoryName, 'GET')

topLevel.description = """The GET method on values is used to retrieve
    tag values from objects matching a query."""

# We could here mention
# href="http://doc.fluidinfo.com/fluidDB/api/draft-values-spec.html">
# /values draft spec</a>.

registry.register(topLevel)

# --- GET /values --------------------------------------------------------

usage = HTTPUsage(
    '', """Search for objects matching a Fluidinfo query, and return the
           value of the requested tags on the matching objects.""")
usage.resourceClass = ValuesResource
topLevel.addUsage(usage)

usage.addArgument(
    Argument(queryArg,
             '''A query string specifying what objects to match. The
       Fluidinfo query language is described
       <a href="http://doc.fluidinfo.com/fluidDB/queries.html">here</a>.''',
             'string',
             None,
             mandatory=True))

usage.addArgument(
    Argument(tagArg,
Beispiel #11
0
        registry.checkResponse(responseType, responseDict, usage, request)
        body = payloads.buildPayload(responseType, responseDict)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)


# ------------------------------ Objects POST -----------------------------
topLevel = HTTPTopLevel(httpObjectCategoryName, 'POST')
topLevel.description = "Create a new Fluidinfo object."
registry.register(topLevel)

# --- POST /objects -------------------------------------------------------

usage = HTTPUsage('', 'Create a new object. You must provide credentials for '
                      'this call to succeed.')
topLevel.addUsage(usage)
usage.resourceClass = ObjectsResource
usage.successCode = http.CREATED

apiDoc.addBadRequestPayload(usage)

apiDoc.addCannotRespondWithPayload(usage)

usage.addReturn(Return(apiDoc.UNAUTHORIZED,
                       'If valid credentials are not provided.'))

usage.addReturn(Return(
    apiDoc.httpCode(usage.successCode),
    'A new object was created without error.'))
Beispiel #12
0
        body = payloads.buildPayload(responseType, responseDict)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)


# ------------------------------ Objects POST -----------------------------
topLevel = HTTPTopLevel(httpObjectCategoryName, 'POST')
topLevel.description = "Create a new Fluidinfo object."
registry.register(topLevel)

# --- POST /objects -------------------------------------------------------

usage = HTTPUsage(
    '', 'Create a new object. You must provide credentials for '
    'this call to succeed.')
topLevel.addUsage(usage)
usage.resourceClass = ObjectsResource
usage.successCode = http.CREATED

apiDoc.addBadRequestPayload(usage)

apiDoc.addCannotRespondWithPayload(usage)

usage.addReturn(
    Return(apiDoc.UNAUTHORIZED, 'If valid credentials are not provided.'))

usage.addReturn(
    Return(apiDoc.httpCode(usage.successCode),
           'A new object was created without error.'))
Beispiel #13
0
                                   NamespacesResource)
        registry.checkRequest(usage, request)
        yield self.facadeClient.deleteNamespace(self.session,
                                                sep.join(request.postpath))
        request.setResponseCode(usage.successCode)


# ------------------------------ Namespaces POST --------------------------
topLevel = HTTPTopLevel(httpNamespaceCategoryName, 'POST')
registry.register(topLevel)


# --- POST /namespaces/NAMESPACE1/NAMESPACE2 ------------------------------

usage = HTTPUsage(apiDoc.NS_NS, 'Create a new namespace.  Intermediate '
                  "namespaces are created automatically if they don't already "
                  'exist.')
topLevel.addUsage(usage)
usage.resourceClass = NamespacesResource
usage.successCode = http.CREATED

usage.addNote(Note("""The new namespace will have permissions set
according to the user's defaults. There is no permission inheritance
in Fluidinfo."""))

usage.addReturn(Return(
    apiDoc.PRECONDITION_FAILED,
    'If the namespace already exists.'))

usage.addReturn(Return(
    apiDoc.NOT_FOUND,
Beispiel #14
0
topLevel = HTTPTopLevel(httpValueCategoryName, 'GET')

topLevel.description = """The GET method on values is used to retrieve
    tag values from objects matching a query."""

# We could here mention
# href="http://doc.fluidinfo.com/fluidDB/api/draft-values-spec.html">
# /values draft spec</a>.

registry.register(topLevel)


# --- GET /values --------------------------------------------------------

usage = HTTPUsage(
    '', """Search for objects matching a Fluidinfo query, and return the
           value of the requested tags on the matching objects.""")
usage.resourceClass = ValuesResource
topLevel.addUsage(usage)

usage.addArgument(Argument(
    queryArg,
    '''A query string specifying what objects to match. The
       Fluidinfo query language is described
       <a href="http://doc.fluidinfo.com/fluidDB/queries.html">here</a>.''',
    'string',
    None,
    mandatory=True))

usage.addArgument(Argument(
    tagArg,
Beispiel #15
0
                return AboutObjectResource(
                    self.facadeClient, self.session, about)


# ------------------------------ About POST -----------------------------
topLevel = HTTPTopLevel(httpAboutCategoryName, 'POST')
topLevel.description = "Create a new object."
registry.register(topLevel)

# --- POST /about -------------------------------------------------------

usage = HTTPUsage('/' + apiDoc.ABOUTSTR, ('''Create a new object with the
    given about value. If there is already a Fluidinfo object whose
    ''' + apiDoc.ABOUT_TAG + ''' tag has the given value, the returned
    object id will be that of the pre-existing object. In this call, and
    all others with an about value in the URI, you must convert
    your about value to UTF-8 and then
    <a href="http://en.wikipedia.org/wiki/Percent-encoding">
    percent-encode</a> it before adding it to the request URI. You must
    provide valid credentials for this call to succeed.
    For an example see the PUT request, below.'''))

topLevel.addUsage(usage)
usage.resourceClass = AboutObjectResource
usage.successCode = http.CREATED

usage.addReturn(Return(
    apiDoc.BAD_REQUEST,
    'The ' + apiDoc.ABOUTSTR + ' argument was not valid UTF-8.'))

apiDoc.addBadRequestPayload(usage)
Beispiel #16
0
        returnValue(body)


# API DOCUMENTATION

# GET on  /recent
topLevel = HTTPTopLevel('recent', 'GET')
topLevel.description = dedent("""
    The GET method on recent is used to retrieve information about the latest
    updated tag values on a given object or user.""")
registry.register(topLevel)

# GET on /recent/objects
usage = HTTPUsage(
    '/objects',
    dedent("""
    To request information on the latest tag values on the objects returned by
    a given query"""))
usage.resourceClass = RecentObjectsActivityResource
usage.addArgument(
    Argument('query',
             dedent("""
    A query string specifying what sorts of objects to get recent activity for.
    The query language is described <a
    href="http://doc.fluidinfo.com/fluidDB/queries.html">here</a>. You must
    convert your query to UTF-8 and then <a href="http://en.wikipedia.org/wiki
    /Percent-encoding">
     percent-encode</a> it before adding it to the request URI
     """),
             'string',
             default=None,
Beispiel #17
0
    tag is first created. Use PUT to adjust the permissions on a given
    namespace or tag.  """
    # TODO: Finish this sentence and add it to the description:
    # To change a user's defaults, do a PUT on.... what exactly?
registry.register(topLevel)


# ------------------------------ Permissions GET --------------------------
topLevel = HTTPTopLevel('permissions', 'GET')
registry.register(topLevel)


# --- GET /permissions/namespaces/NAMESPACE1/NAMESPACE2 ------------

usage = HTTPUsage(
    '/' + httpNamespaceCategoryName + apiDoc.NS_NS,
    """Get the permissions on a namespace: the open/closed policy,
    and the set of exceptions to the policy.""")
usage.resourceClass = ConcreteNamespacePermissionResource
topLevel.addUsage(usage)

possibleActions = ', '.join(permissions.actionsByCategory[
    namespaceCategoryName])

usage.addArgument(Argument(
    actionArg,
    """The action whose permissions information is
    sought. Possible values are: """ + possibleActions + '.',
    'string',
    mandatory=True))

apiDoc.addMissingIntermediateNs(usage)
Beispiel #18
0
        usage = registry.findUsage(httpTagCategoryName, 'DELETE', TagsResource)
        registry.checkRequest(usage, request)
        yield self.facadeClient.deleteTag(self.session,
                                          sep.join(request.postpath))
        request.setResponseCode(usage.successCode)


# ------------------------------ Tags POST --------------------------
topLevel = HTTPTopLevel(httpTagCategoryName, 'POST')
registry.register(topLevel)


# --- POST /tags/NAMESPACE1/NAMESPACE2 ------------------------

usage = HTTPUsage(apiDoc.NS_NS,
                  'Add a tag name to a namespace.  Intermediate namespaces '
                  "are created automatically if they don't already exist.")
topLevel.addUsage(usage)
usage.resourceClass = TagsResource
usage.successCode = http.CREATED

requestPayload = JSONPayload()
requestPayload.addField(PayloadField(
    'name', unicode, 'The name of the new tag.'))
requestPayload.addField(PayloadField(
    'description', unicode, 'A description of the tag.', mayBeNone=True))
requestPayload.addField(PayloadField(
    'indexed', bool, 'Whether or not tag values should be indexed.'))

usage.addRequestPayload(requestPayload)
Beispiel #19
0
        usage = registry.findUsage(httpNamespaceCategoryName, 'DELETE',
                                   NamespacesResource)
        registry.checkRequest(usage, request)
        yield self.facadeClient.deleteNamespace(self.session,
                                                sep.join(request.postpath))
        request.setResponseCode(usage.successCode)


# ------------------------------ Namespaces POST --------------------------
topLevel = HTTPTopLevel(httpNamespaceCategoryName, 'POST')
registry.register(topLevel)

# --- POST /namespaces/NAMESPACE1/NAMESPACE2 ------------------------------

usage = HTTPUsage(
    apiDoc.NS_NS, 'Create a new namespace.  Intermediate '
    "namespaces are created automatically if they don't already "
    'exist.')
topLevel.addUsage(usage)
usage.resourceClass = NamespacesResource
usage.successCode = http.CREATED

usage.addNote(
    Note("""The new namespace will have permissions set
according to the user's defaults. There is no permission inheritance
in Fluidinfo."""))

usage.addReturn(
    Return(apiDoc.PRECONDITION_FAILED, 'If the namespace already exists.'))

usage.addReturn(
    Return(
Beispiel #20
0
    POST is not supported on permissions, because permissions are
    automatically set from a user's default permissions when a namespace or
    tag is first created. Use PUT to adjust the permissions on a given
    namespace or tag.  """
# TODO: Finish this sentence and add it to the description:
# To change a user's defaults, do a PUT on.... what exactly?
registry.register(topLevel)

# ------------------------------ Permissions GET --------------------------
topLevel = HTTPTopLevel('permissions', 'GET')
registry.register(topLevel)

# --- GET /permissions/namespaces/NAMESPACE1/NAMESPACE2 ------------

usage = HTTPUsage(
    '/' + httpNamespaceCategoryName + apiDoc.NS_NS,
    """Get the permissions on a namespace: the open/closed policy,
    and the set of exceptions to the policy.""")
usage.resourceClass = ConcreteNamespacePermissionResource
topLevel.addUsage(usage)

possibleActions = ', '.join(
    permissions.actionsByCategory[namespaceCategoryName])

usage.addArgument(
    Argument(actionArg,
             """The action whose permissions information is
    sought. Possible values are: """ + possibleActions + '.',
             'string',
             mandatory=True))

apiDoc.addMissingIntermediateNs(usage)