Merge lp:~mithrandi/txfluiddb/object-operations into lp:~txfluiddb-maint/txfluiddb/trunk-obsolete-1.6

Proposed by Tristan Seligmann
Status: Merged
Merged at revision: 3
Proposed branch: lp:~mithrandi/txfluiddb/object-operations
Merge into: lp:~txfluiddb-maint/txfluiddb/trunk-obsolete-1.6
Diff against target: None lines
To merge this branch: bzr merge lp:~mithrandi/txfluiddb/object-operations
Reviewer Review Type Date Requested Status
Tristan Seligmann Needs Resubmitting
Jonathan Jacobs (community) Needs Fixing
Review via email: mp+10500@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Tristan Seligmann (mithrandi) wrote :

Implement operations on objects.

Revision history for this message
Jonathan Jacobs (jjacobs) wrote :

  1. `Endpoint.submit`'s parameters need documentation, specifically the "data" parameter probably needs some careful and clear documentation.

  2. The `agent` parameter to `getPage` should probably include a version.

  3. There are some klaxons going off in `Object.get`. You test for the "valueType" key, and then read "valueEncoding", test it against a value and then create a blob with "valueType". It looks like "valueEncoding" was a brainfart. Also, why not use the "encoding" value (that you tested) as the parameter to `decode`? See point 5.

  4. `Object.query`'s return value is not documented.

  5. The description of the return value for `Object.getTags` is slightly confusing.

  6. There isn't any test coverage for the potential exception / errback in `Object.get`.

  7. `ObjectTests.test_getInteger` incorrectly documents the type as "integer", you probably meant "int".

  8. In "ObjectTests", `test_setTag`, `test_setBlob`, `test_createObjectWithAbout` have no docs.

  9. There are a handful of lines longer than 80 columns.

review: Needs Fixing
Revision history for this message
Jonathan Jacobs (jjacobs) wrote :

> parameter to `decode`? See point 5.

I meant point 6.

13. By Tristan Seligmann <tristan@viridian>

Improve Endpoint.submit documentation.

14. By Tristan Seligmann <tristan@viridian>

Document Object.query return value.

15. By Tristan Seligmann <tristan@viridian>

Fix test docstring.

16. By Tristan Seligmann <tristan@viridian>

Tests for encoding stuff.

17. By Tristan Seligmann

Test unsupported encodings.

18. By Tristan Seligmann

Split long lines.

Revision history for this message
Tristan Seligmann (mithrandi) wrote :

I believe I've addressed all of these points except for point 8; I'm not sure how to write a useful docstring for those tests. Any suggestions?

Revision history for this message
Tristan Seligmann (mithrandi) wrote :

Testing something.

review: Needs Resubmitting
Revision history for this message
Jonathan Jacobs (jjacobs) wrote :

> I believe I've addressed all of these points except for point 8; I'm not sure
> how to write a useful docstring for those tests. Any suggestions?

My only suggestion is the obvious one, attempt to concisely explain the desired behaviour of the code. What is supposed to happen? etc.

I noticed that several other tests are missing docstrings too.

19. By Tristan Seligmann

Docstrings.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'LICENSE'
--- LICENSE 2009-08-17 23:05:23 +0000
+++ LICENSE 2009-08-21 00:05:49 +0000
@@ -1,4 +1,4 @@
1Copyright (c) 2009 Tristan Seligmann1Copyright © 2009 Tristan Seligmann
22
3Permission is hereby granted, free of charge, to any person obtaining3Permission is hereby granted, free of charge, to any person obtaining
4a copy of this software and associated documentation files (the4a copy of this software and associated documentation files (the
55
=== modified file 'txfluiddb/client.py'
--- txfluiddb/client.py 2009-08-19 20:33:58 +0000
+++ txfluiddb/client.py 2009-08-21 00:42:26 +0000
@@ -15,7 +15,7 @@
15 @type components: C{list} of C{unicode}15 @type components: C{list} of C{unicode}
16 @ivar components: A list of path components for this identifier.16 @ivar components: A list of path components for this identifier.
1717
18 @type collectionName: C{str}18 @type collectionName: C{unicode}
19 @cvar collectionName: The top-level path component under which these19 @cvar collectionName: The top-level path component under which these
20 identifiers exist.20 identifiers exist.
2121
@@ -66,13 +66,19 @@
66 return u'/'.join(self.components)66 return u'/'.join(self.components)
6767
6868
69 def getURL(self, endpoint, prefix=None):69 def getURL(self, endpoint, prefix=None, suffix=[]):
70 """70 """
71 Get the URL for this path as accessed through the given endpoint.71 Get the URL for this path as accessed through the given endpoint.
7272
73 @type endpoint: L{Endpoint}73 @type endpoint: L{Endpoint}
74 @param endpoint: The endpoint to operate through.74 @param endpoint: The endpoint to operate through.
7575
76 @type prefix: C{list} of C{unicode}
77 @param prefix: A list of components to prepend before this path.
78
79 @type suffix: C{list} of C{unicode}
80 @param suffix: A list of components to append after this path.
81
76 @rtype: C{str}82 @rtype: C{str}
77 """83 """
78 if self.collectionName is None:84 if self.collectionName is None:
@@ -83,12 +89,11 @@
83 components.append(self.collectionName)89 components.append(self.collectionName)
84 else:90 else:
85 components.extend(prefix)91 components.extend(prefix)
8692 components.extend(self.components)
87 for component in self.components:93 components.extend(suffix)
88 encoded = component.encode('utf-8')94
89 quoted = quote(encoded, safe='')95 components = [quote(component.encode('utf-8'), safe='')
90 components.append(quoted)96 for component in components]
91
92 return endpoint.getRootURL() + '/'.join(components)97 return endpoint.getRootURL() + '/'.join(components)
9398
9499
@@ -97,7 +102,7 @@
97 """102 """
98 Representation of a FluidDB namespace.103 Representation of a FluidDB namespace.
99 """104 """
100 collectionName = 'namespaces'105 collectionName = u'namespaces'
101106
102107
103 def child(self, name):108 def child(self, name):
@@ -141,7 +146,7 @@
141 @rtype: C{Deferred} -> C{unicode}146 @rtype: C{Deferred} -> C{unicode}
142 @return: The description.147 @return: The description.
143 """148 """
144 url = self.getURL(endpoint) + '?' + urlencode({'returnDescription': 'true'})149 url = self.getURL(endpoint) + '?returnDescription=true'
145 d = endpoint.submit(url=url, method='GET')150 d = endpoint.submit(url=url, method='GET')
146 return d.addCallback(lambda res: res[u'description'])151 return d.addCallback(lambda res: res[u'description'])
147152
@@ -179,7 +184,7 @@
179 namespaces.append(self.child(name))184 namespaces.append(self.child(name))
180 return namespaces185 return namespaces
181186
182 url = self.getURL(endpoint) + '?' + urlencode({'returnNamespaces': 'true'})187 url = self.getURL(endpoint) + '?returnNamespaces=true'
183 d = endpoint.submit(url=url, method='GET')188 d = endpoint.submit(url=url, method='GET')
184 return d.addCallback(_parseResponse)189 return d.addCallback(_parseResponse)
185190
@@ -200,7 +205,7 @@
200 namespaces.append(self.tag(name))205 namespaces.append(self.tag(name))
201 return namespaces206 return namespaces
202207
203 url = self.getURL(endpoint) + '?' + urlencode({'returnTags': 'true'})208 url = self.getURL(endpoint) + '?returnTags=true'
204 d = endpoint.submit(url=url, method='GET')209 d = endpoint.submit(url=url, method='GET')
205 return d.addCallback(_parseResponse)210 return d.addCallback(_parseResponse)
206211
@@ -273,7 +278,7 @@
273 """278 """
274 Representation of a FluidDB tag.279 Representation of a FluidDB tag.
275 """280 """
276 collectionName = 'tags'281 collectionName = u'tags'
277282
278283
279 def getDescription(self, endpoint):284 def getDescription(self, endpoint):
@@ -286,7 +291,7 @@
286 @rtype: C{Deferred} -> C{unicode}291 @rtype: C{Deferred} -> C{unicode}
287 @return: The description.292 @return: The description.
288 """293 """
289 url = self.getURL(endpoint) + '?' + urlencode({'returnDescription': 'true'})294 url = self.getURL(endpoint) + '?returnDescription=true'
290 d = endpoint.submit(url=url, method='GET')295 d = endpoint.submit(url=url, method='GET')
291 return d.addCallback(lambda res: res[u'description'])296 return d.addCallback(lambda res: res[u'description'])
292297
@@ -356,12 +361,15 @@
356 return getPage(*a, **kw)361 return getPage(*a, **kw)
357362
358363
359 def submit(self, url, method, data=None):364 def submit(self, url, method, data=None, headers=None):
360 """365 """
361 Submit a request through this endpoint.366 Submit a request through this endpoint.
362 """367 """
363 headers = {'Accept': 'application/json'}368 if headers is None:
364 if data is not None:369 headers = {}
370
371 headers['Accept'] = 'application/json'
372 if data is not None and not isinstance(data, str):
365 data = json.dumps(data)373 data = json.dumps(data)
366 headers['Content-Type'] = 'application/json'374 headers['Content-Type'] = 'application/json'
367375
@@ -369,5 +377,202 @@
369 if res:377 if res:
370 return json.loads(unicode(res, 'utf-8'))378 return json.loads(unicode(res, 'utf-8'))
371379
372 d = self.getPage(url=url, method=method, postdata=data, headers=headers, agent='txFluidDB')380 d = self.getPage(url=url,
381 method=method,
382 postdata=data,
383 headers=headers,
384 agent='txFluidDB')
373 return d.addCallback(_parse)385 return d.addCallback(_parse)
386
387
388
389class Object(_HasPath):
390 """
391 A FluidDB object.
392
393 @type uuid: C{unicode}
394 @ivar uuid: The UUID of the object.
395 """
396 collectionName = u'objects'
397
398
399 def __init__(self, uuid):
400 self.uuid = uuid
401
402
403 @property
404 def components(self):
405 """
406 Our only path component is the object UUID.
407 """
408 return [self.uuid]
409
410
411 @classmethod
412 def create(cls, endpoint, about=None):
413 """
414 Create a new object.
415
416 @type endpoint: L{Endpoint}
417 @param endpoint: The endpoint to operate through.
418
419 @type about: C{unicode} or C{None}
420 @param about: The value for the about tag, if desired.
421
422 @rtype: C{Deferred} -> L{Object}
423 @return: The newly created object.
424 """
425 url = endpoint.getRootURL() + 'objects'
426 data = {}
427 if about is not None:
428 data[u'about'] = about
429
430 def _parseResponse(response):
431 return Object(response[u'id'])
432
433 d = endpoint.submit(url=url, method='POST', data=data)
434 return d.addCallback(_parseResponse)
435
436
437 @classmethod
438 def query(cls, endpoint, query):
439 """
440 Search for objects that match a query.
441
442 @type endpoint: L{Endpoint}
443 @param endpoint: The endpoint to operate through.
444
445 @type query: C{unicode}
446 @param query: A query string to search on.
447 """
448 qs = '?' + urlencode({'query': query.encode('utf-8')})
449 url = endpoint.getRootURL() + 'objects' + qs
450
451 def _parseResponse(response):
452 return [Object(uuid) for uuid in response['ids']]
453
454 d = endpoint.submit(url=url, method='GET')
455 return d.addCallback(_parseResponse)
456
457
458 def getTags(self, endpoint):
459 """
460 Get the visible tags on this object.
461
462 @type endpoint: L{Endpoint}
463 @param endpoint: The endpoint to operate through.
464
465 @rtype: C{Deferred} -> (C{unicode}, C{list} of L{Tag})
466 @return: A tuple of the about tag value and the list of tags.
467 """
468 def _parseResponse(response):
469 about = response[u'about']
470 tags = [Tag(*path.split(u'/')) for path in response[u'tagPaths']]
471 return (about, tags)
472
473 url = self.getURL(endpoint)
474 d = endpoint.submit(url=url,
475 method='GET',
476 data={u'showAbout': True})
477 return d.addCallback(_parseResponse)
478
479
480 def get(self, endpoint, tag):
481 """
482 Get the value of a tag on this object.
483
484 @type endpoint: L{Endpoint}
485 @param endpoint: The endpoint to operate through.
486
487 @type tag: L{Tag}
488 @param tag: The tag to retrieve.
489
490 @rtype: Varies depending on what value is stored.
491 @return: The stored value.
492 """
493 def _parseResponse(response):
494 value = response[u'value']
495 if u'valueType' in response:
496 encoding = response[u'valueEncoding']
497 if encoding != u'base-64':
498 raise ValueError('Unsupported encoding received: %r' % encoding)
499 value = value.decode('base-64')
500 return Blob(response[u'valueType'], value)
501 return value
502
503 url = self.getURL(endpoint, suffix=tag.components) + '?format=json'
504 d = endpoint.submit(url=url,
505 method='GET',
506 headers={'Accept-Encoding': 'base-64'})
507 return d.addCallback(_parseResponse)
508
509
510 def set(self, endpoint, tag, value):
511 """
512 Set the value of a tag on this object.
513
514 @type endpoint: L{Endpoint}
515 @param endpoint: The endpoint to operate through.
516
517 @type tag: L{Tag}
518 @param tag: The tag to set or replace.
519
520 @type value: Any JSON-encodable value
521 @param value: The value to store.
522 """
523 url = self.getURL(endpoint, suffix=tag.components) + '?format=json'
524 return endpoint.submit(url=url,
525 method='PUT',
526 data={u'value': value})
527
528
529 def setBlob(self, endpoint, tag, value):
530 """
531 Set the value of a tag on this object to a blob.
532
533 @type endpoint: L{Endpoint}
534 @param endpoint: The endpoint to operate through.
535
536 @type tag: L{Tag}
537 @param tag: The tag to set or replace.
538
539 @type value: L{Blob}
540 @param value: The value to store.
541 """
542 url = self.getURL(endpoint, suffix=tag.components)
543 return endpoint.submit(url=url,
544 method='PUT',
545 headers={'Content-Type': value.contentType},
546 data=value.data)
547
548
549 def delete(self, endpoint, tag):
550 """
551 Delete a tag from this object.
552
553 Note that FluidDB does not support deleting objects themselves.
554
555 @type endpoint: L{Endpoint}
556 @param endpoint: The endpoint to operate through.
557
558 @type tag: L{Tag}
559 @param tag: The tag to retrieve.
560 """
561 url = self.getURL(endpoint, suffix=tag.components)
562 return endpoint.submit(url=url, method='DELETE')
563
564
565
566class Blob(object):
567 """
568 A binary blob with a MIME content type.
569
570 @type contentType: C{unicode}
571 @ivar contentType: The MIME content-type of the data.
572
573 @type data: C{str}
574 @ivar data: The actual data.
575 """
576 def __init__(self, contentType, data):
577 self.contentType = contentType
578 self.data = data
374579
=== modified file 'txfluiddb/test/test_client.py'
--- txfluiddb/test/test_client.py 2009-08-19 20:33:58 +0000
+++ txfluiddb/test/test_client.py 2009-08-21 00:42:26 +0000
@@ -4,7 +4,7 @@
4import simplejson as json4import simplejson as json
55
6from txfluiddb.errors import InvalidName6from txfluiddb.errors import InvalidName
7from txfluiddb.client import Namespace, Tag, Endpoint, _HasPath7from txfluiddb.client import Namespace, Tag, Endpoint, _HasPath, Object, Blob
88
99
1010
@@ -44,6 +44,28 @@
44 'http://fluiddb.test.url/tests/foo')44 'http://fluiddb.test.url/tests/foo')
4545
4646
47 def test_getURLPrefix(self):
48 """
49 Passing prefix to getURL prepends the given components to the path.
50 """
51 endpoint = Endpoint('http://fluiddb.test.url/')
52 path = _HasPath(u'foo')
53 path.collectionName = 'tests'
54 self.assertEqual(path.getURL(endpoint, prefix=[u'quux', u'42']),
55 'http://fluiddb.test.url/quux/42/foo')
56
57
58 def test_getURLSuffix(self):
59 """
60 Passing suffix to getURL appends the given components to the path.
61 """
62 endpoint = Endpoint('http://fluiddb.test.url/')
63 path = _HasPath(u'foo')
64 path.collectionName = 'tests'
65 self.assertEqual(path.getURL(endpoint, suffix=[u'quux', u'42']),
66 'http://fluiddb.test.url/tests/foo/quux/42')
67
68
47 def test_urlEncoding(self):69 def test_urlEncoding(self):
48 """70 """
49 URL encoding is done according to IRI rules.71 URL encoding is done according to IRI rules.
@@ -374,3 +396,199 @@
374 endpoint = Endpoint('http://fluiddb.test.url/', '20090817')396 endpoint = Endpoint('http://fluiddb.test.url/', '20090817')
375 self.assertEqual(endpoint.getRootURL(),397 self.assertEqual(endpoint.getRootURL(),
376 'http://fluiddb.test.url/20090817/')398 'http://fluiddb.test.url/20090817/')
399
400
401
402class ObjectTests(TestCase):
403 """
404 Tests for L{Object}.
405 """
406 def setUp(self):
407 self.endpoint = MockEndpoint('http://fluiddb.test.url/')
408
409
410 def test_getTags(self):
411 """
412 The getTags method returns the about value and the list of tags.
413 """
414 response = {u'about': u'Testing object',
415 u'tagPaths': [u'test/tag1', u'test/tag2']}
416 self.endpoint.response = json.dumps(response)
417
418 def _gotResponse(response):
419 about, tags = response
420 self.assertEqual(about, u'Testing object')
421 self.assertEqual(len(tags), 2)
422 tag1, tag2 = tags
423 self.assertIsInstance(tag1, Tag)
424 self.assertEqual(tag1.getPath(), u'test/tag1')
425 self.assertIsInstance(tag2, Tag)
426 self.assertEqual(tag2.getPath(), u'test/tag2')
427
428 obj = Object(u'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx')
429 d = obj.getTags(self.endpoint).addCallback(_gotResponse)
430 self.assertEqual(self.endpoint.method, 'GET')
431 self.assertEqual(
432 self.endpoint.url,
433 'http://fluiddb.test.url/objects/xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx')
434 self.assertEqual(json.loads(self.endpoint.data),
435 {u'showAbout': True})
436 return d
437
438
439 def makeGetRequest(self, response):
440 """
441 Utility wrapper for testing L{Object.get} operations.
442 """
443 self.endpoint.response = json.dumps(response)
444 obj = Object(u'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx')
445 tag = Namespace(u'test').child(u'tag')
446 d = obj.get(self.endpoint, tag)
447 self.assertEqual(self.endpoint.method, 'GET')
448 self.assertEqual(self.endpoint.data, None)
449 self.assertEqual(
450 self.endpoint.url,
451 'http://fluiddb.test.url/objects/xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx/test/tag?format=json')
452 return d
453
454
455 def test_getString(self):
456 """
457 Retrieving a JSON string value results in a C{unicode} object.
458 """
459 response = {u'value': u'Data goes where?'}
460 def _gotResponse(response):
461 self.assertIsInstance(response, unicode)
462 self.assertEqual(response, u'Data goes where?')
463 return self.makeGetRequest(response).addCallback(_gotResponse)
464
465
466 def test_getInteger(self):
467 """
468 Retrieving a JSON integer value results in an C{integer} object.
469 """
470 response = {u'value': 42}
471 def _gotResponse(response):
472 self.assertEqual(response, 42)
473 return self.makeGetRequest(response).addCallback(_gotResponse)
474
475
476 def test_getBlob(self):
477 """
478 Retrieving a binary value results in a C{Blob} object.
479 """
480 response = {u'value': u'PHA+Zm9vPC9wPg==',
481 u'valueEncoding': u'base-64',
482 u'valueType': u'text/html'}
483 def _gotResponse(response):
484 self.assertEqual(self.endpoint.headers['Accept-Encoding'], 'base-64')
485 self.assertEqual(response.contentType, u'text/html')
486 self.assertEqual(response.data, '<p>foo</p>')
487 return self.makeGetRequest(response).addCallback(_gotResponse)
488
489
490 def test_deleteTag(self):
491 """
492 Deleting a tag returns nothing if successful.
493 """
494 self.endpoint.response = ''
495
496 obj = Object(u'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx')
497 tag = Namespace(u'test').child(u'tag')
498 d = obj.delete(self.endpoint, tag)
499 self.assertEqual(self.endpoint.method, 'DELETE')
500 self.assertEqual(
501 self.endpoint.url,
502 'http://fluiddb.test.url/objects/xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx/test/tag')
503 self.assertEqual(self.endpoint.data, None)
504 return d
505
506
507 def test_setTag(self):
508 self.endpoint.response = ''
509
510 obj = Object(u'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx')
511 tag = Namespace(u'test').child(u'tag')
512 d = obj.set(self.endpoint, tag, 42)
513 self.assertEqual(self.endpoint.method, 'PUT')
514 self.assertEqual(
515 self.endpoint.url,
516 'http://fluiddb.test.url/objects/xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx/test/tag?format=json')
517 self.assertEqual(json.loads(self.endpoint.data),
518 {u'value': 42})
519 return d
520
521
522 def test_setBlob(self):
523 self.endpoint.response = ''
524
525 obj = Object(u'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx')
526 tag = Namespace(u'test').child(u'tag')
527 blob = Blob(u'text/html', '<p>foo</p>')
528 d = obj.setBlob(self.endpoint, tag, blob)
529 self.assertEqual(self.endpoint.method, 'PUT')
530 self.assertEqual(
531 self.endpoint.url,
532 'http://fluiddb.test.url/objects/xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx/test/tag')
533 self.assertEqual(self.endpoint.data, '<p>foo</p>')
534 self.assertEqual(self.endpoint.headers['Content-Type'], 'text/html')
535 return d
536
537
538 def test_createObject(self):
539 """
540 Creating an object returns the newly created object.
541 """
542 response = {u'URI': u'http://fluiddb.test.url/objects/xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx',
543 u'id': u'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'}
544 self.endpoint.response = json.dumps(response)
545
546 def _gotResponse(obj):
547 self.assertIsInstance(obj, Object)
548 self.assertEqual(obj.uuid, u'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx')
549
550 d = Object.create(self.endpoint).addCallback(_gotResponse)
551 self.assertEqual(self.endpoint.method, 'POST')
552 self.assertEqual(self.endpoint.url, 'http://fluiddb.test.url/objects')
553 self.assertEqual(json.loads(self.endpoint.data), {})
554 return d
555
556
557 def test_createObjectWithAbout(self):
558 response = {u'URI': u'http://fluiddb.test.url/objects/xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx',
559 u'id': u'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'}
560 self.endpoint.response = json.dumps(response)
561
562 def _gotResponse(obj):
563 self.assertIsInstance(obj, Object)
564 self.assertEqual(obj.uuid, u'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx')
565
566 d = Object.create(self.endpoint, u'New object').addCallback(_gotResponse)
567 self.assertEqual(self.endpoint.method, 'POST')
568 self.assertEqual(self.endpoint.url, 'http://fluiddb.test.url/objects')
569 self.assertEqual(json.loads(self.endpoint.data),
570 {u'about': u'New object'})
571 return d
572
573
574 def test_query(self):
575 """
576 Querying returns all objects matching the query.
577 """
578 response = {u'ids': [u'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxx1',
579 u'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxx2']}
580 self.endpoint.response = json.dumps(response)
581
582 def _gotResponse(objs):
583 self.assertEqual(len(objs), 2)
584 obj1, obj2 = objs
585 self.assertIsInstance(obj1, Object)
586 self.assertEqual(obj1.uuid, u'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxx1')
587 self.assertIsInstance(obj2, Object)
588 self.assertEqual(obj2.uuid, u'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxx2')
589
590 d = Object.query(self.endpoint, u'has fluiddb/about').addCallback(_gotResponse)
591 self.assertEqual(self.endpoint.method, 'GET')
592 self.assertEqual(self.endpoint.url, 'http://fluiddb.test.url/objects?query=has+fluiddb%2Fabout')
593 self.assertEqual(self.endpoint.data, None)
594 return d

Subscribers

People subscribed via source and target branches