Merge lp:~terrycojones/txfluiddb/add-slash-values-support-821418 into lp:~terrycojones/txfluiddb/add-exists-tests-for-namespaces-and-tags

Proposed by Terry Jones
Status: Needs review
Proposed branch: lp:~terrycojones/txfluiddb/add-slash-values-support-821418
Merge into: lp:~terrycojones/txfluiddb/add-exists-tests-for-namespaces-and-tags
Diff against target: 339 lines (+294/-3)
3 files modified
setup.py (+1/-1)
txfluiddb/client.py (+73/-0)
txfluiddb/test/test_client.py (+220/-2)
To merge this branch: bzr merge lp:~terrycojones/txfluiddb/add-slash-values-support-821418
Reviewer Review Type Date Requested Status
Terry Jones Pending
Review via email: mp+70650@code.launchpad.net

Description of the change

A simple approach to letting txFluidDB call the /values endpoint in Fluidinfo.

To post a comment you must log in.

Unmerged revisions

18. By Terry Jones

Bumped version number.

17. By Terry Jones

Added simple support for GET, PUT, DELETE on /values.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'setup.py'
--- setup.py 2011-07-31 21:38:07 +0000
+++ setup.py 2011-08-06 13:24:39 +0000
@@ -5,7 +5,7 @@
55
6setup(6setup(
7 name = 'txfluiddb',7 name = 'txfluiddb',
8 version = '0.1.1',8 version = '0.1.2',
9 packages = ['txfluiddb'],9 packages = ['txfluiddb'],
10 author = 'Tristan Seligmann',10 author = 'Tristan Seligmann',
11)11)
1212
=== modified file 'txfluiddb/client.py'
--- txfluiddb/client.py 2011-07-31 21:29:38 +0000
+++ txfluiddb/client.py 2011-08-06 13:24:39 +0000
@@ -436,6 +436,79 @@
436 collectionName = u'tag-values'436 collectionName = u'tag-values'
437437
438438
439class Values(object):
440 """
441 Provides for operations on sets of tag values using the Fluidinfo
442 /values endpoint.
443 """
444
445
446 def get(self, endpoint, query, tags):
447 """
448 Get the tag values matching a query.
449
450 @type endpoint: L{Endpoint}
451 @param endpoint: The endpoint to operate through.
452
453 @type query: C{unicode}
454 @param query: The query specifiying which Fluidinfo
455 objects to operate on.
456
457 @type tags: C{list} of C{unicode}
458 @param tags: The tags whose values are wanted.
459
460 @rtype: C{Deferred}
461 """
462 url = '%svalues?%s' % (
463 endpoint.getRootURL(),
464 urlencode({
465 'query' : query.encode('utf-8'),
466 'tag' : [tag.encode('utf-8') for tag in tags],
467 }, doseq=True))
468 return endpoint.submit(url=url, method='GET')
469
470
471 def put(self, endpoint, payload):
472 """
473 Delete tag values matching queries.
474
475 @type endpoint: L{Endpoint}
476 @param endpoint: The endpoint to operate through.
477
478 @type payload: C{dict}
479 @param payload: A dictionary to be converted to JSON
480 for the request payload to the /values endpoint.
481
482 @rtype: C{Deferred}
483 """
484 return endpoint.submit(url='%svalues' % endpoint.getRootURL(),
485 method='PUT')
486
487
488 def delete(self, endpoint, query, tags):
489 """
490 Delete the tag values matching a query.
491
492 @type endpoint: L{Endpoint}
493 @param endpoint: The endpoint to operate through.
494
495 @type query: C{unicode}
496 @param query: The query specifiying which Fluidinfo
497 objects to operate on.
498
499 @type tags: C{list} of C{unicode}
500 @param tags: The tags whose values should be deleted.
501
502 @rtype: C{Deferred}
503 """
504 url = '%svalues?%s' % (
505 endpoint.getRootURL(),
506 urlencode({
507 'query' : query.encode('utf-8'),
508 'tag' : [tag.encode('utf-8') for tag in tags],
509 }, doseq=True))
510 return endpoint.submit(url=url, method='DELETE')
511
439512
440class BasicCreds(object):513class BasicCreds(object):
441 """514 """
442515
=== modified file 'txfluiddb/test/test_client.py'
--- txfluiddb/test/test_client.py 2011-07-31 21:29:38 +0000
+++ txfluiddb/test/test_client.py 2011-08-06 13:24:39 +0000
@@ -1,11 +1,13 @@
1from twisted.trial.unittest import TestCase1from twisted.trial.unittest import TestCase
2from twisted.internet.defer import succeed, fail2from twisted.internet.defer import succeed, fail
33
4from urllib import splitquery
5
4import simplejson as json6import simplejson as json
57
6from txfluiddb.errors import InvalidName8from txfluiddb.errors import InvalidName
7from txfluiddb.client import (9from txfluiddb.client import (Namespace, Tag, Values, Endpoint, _HasPath,
8 Namespace, Tag, Endpoint, _HasPath, Object, Blob, BasicCreds, loads)10 Object, Blob, BasicCreds, loads)
9from txfluiddb.http import HTTPError11from txfluiddb.http import HTTPError
1012
1113
@@ -623,6 +625,222 @@
623 return d625 return d
624626
625627
628class ValuesTests(TestCase):
629 """
630 Tests for the /values URI endpoint on Fluidinfo.
631 """
632 def setUp(self):
633 self.endpoint = MockEndpoint('http://fluiddb.url/')
634 self.values = Values()
635
636
637 def testGetMethodAndURI(self):
638 """
639 Check that the requested URI for GET starts with the /values
640 endpoint and that the request method is correct.
641 """
642 self.endpoint.response = None
643 d = self.values.get(self.endpoint, u'fake query', [u'fake tag'])
644 self.assertEqual(self.endpoint.method, 'GET')
645 self.assertTrue(
646 self.endpoint.url.startswith('http://fluiddb.url/values'))
647 return d
648
649
650 def testGetTagCountAndContent(self):
651 """
652 Check that the requested URI has the expected number of tag=
653 arguments and that the expected values are all present.
654 """
655 self.endpoint.response = None
656 d = self.values.get(
657 self.endpoint,
658 query=u'has fun/eating',
659 tags=[u'hey/you', u'who/me', u'yes/you'])
660 self.assertEqual(3, self.endpoint.url.count('tag='))
661 self.assertTrue(1, self.endpoint.url.count('tag=hey%2Fyou'))
662 self.assertTrue(1, self.endpoint.url.count('tag=who%2Fme'))
663 self.assertTrue(1, self.endpoint.url.count('tag=yes%2Fyou'))
664 return d
665
666
667 def testGetQueryCount(self):
668 """
669 Check that the requested URI has one query= argument, with the
670 expected value.
671 """
672 self.endpoint.response = None
673 d = self.values.get(
674 self.endpoint,
675 query=u'has fun/eating',
676 tags=[u'hey/you'])
677 self.assertEqual(1, self.endpoint.url.count('query='))
678 self.assertTrue(1, self.endpoint.url.count('query=has+fun%2Feating'))
679 return d
680
681
682 def testGetTagURIEncoding(self):
683 """
684 Check that the requested tag name is properly UTF-8 and %-encoded
685 in the request URI.
686 """
687 self.endpoint.response = None
688 d = self.values.get(
689 self.endpoint,
690 query=u'has fun/eating',
691 tags=[u'hey/y \xF2 u'])
692 _, query = splitquery(self.endpoint.url)
693 args = query.split('&')
694 # Find the argument that starts with tag=
695 if args[0].startswith('tag='):
696 arg = args[0]
697 else:
698 arg = args[1]
699 value = arg.split('=')[1]
700 # The argument value should have its '/' %-encoded, the spaces
701 # converted to '+', and the %-encoded UTF-8 of the unicode
702 # \xF2 char.
703 self.assertEqual('hey%2Fy+%C3%B2+u', value)
704 return d
705
706
707 def testGetQueryURIEncoding(self):
708 """
709 Check that the requested query is properly UTF-8 and %-encoded in
710 the request URI.
711 """
712 response = {}
713 self.endpoint.response = json.dumps(response)
714 d = self.values.get(
715 self.endpoint,
716 query=u'joe/blow = "embedded/slash with \xF1"',
717 tags=[u'hey/you'])
718 _, query = splitquery(self.endpoint.url)
719 args = query.split('&')
720 # Find the argument that starts with query=
721 if args[0].startswith('query='):
722 arg = args[0]
723 else:
724 arg = args[1]
725 value = arg.split('=')[1]
726 # The argument value should have the '/', '=' and '"' %-encoded,
727 # the spaces converted to '+', and the %-encoded UTF-8 of the
728 # unicode \xF1 char.
729 self.assertEqual('joe%2Fblow+%3D+%22embedded%2Fslash+with+%C3%B1%22',
730 value)
731 return d
732
733
734 def testPutMethodAndURI(self):
735 """
736 Check that the requested URI for PUT has just the /values endpoint
737 (the details of the PUT request are sent in the payload) and that
738 the request method is correct.
739 """
740 self.endpoint.response = None
741 d = self.values.put(self.endpoint, None)
742 self.assertEqual(self.endpoint.method, 'PUT')
743 self.assertEqual(self.endpoint.url, 'http://fluiddb.url/values')
744 return d
745
746
747 def testDeleteMethodAndURI(self):
748 """
749 Check that the requested URI for DELETE starts with the /values
750 endpoint and that the request method is correct.
751 """
752 self.endpoint.response = None
753 d = self.values.delete(self.endpoint, u'fake query', [u'fake tag'])
754 self.assertEqual(self.endpoint.method, 'DELETE')
755 self.assertTrue(
756 self.endpoint.url.startswith('http://fluiddb.url/values'))
757 return d
758
759
760 def testDeleteTagCountAndContent(self):
761 """
762 Check that the requested URI has the expected number of tag=
763 arguments and that the expected values are all present.
764 """
765 self.endpoint.response = None
766 d = self.values.delete(
767 self.endpoint,
768 query=u'has fun/eating',
769 tags=[u'hey/you', u'who/me', u'yes/you'])
770 self.assertEqual(3, self.endpoint.url.count('tag='))
771 self.assertTrue(1, self.endpoint.url.count('tag=hey%2Fyou'))
772 self.assertTrue(1, self.endpoint.url.count('tag=who%2Fme'))
773 self.assertTrue(1, self.endpoint.url.count('tag=yes%2Fyou'))
774 return d
775
776
777 def testDeleteQueryCount(self):
778 """
779 Check that the requested URI has one query= argument, with the
780 expected value.
781 """
782 self.endpoint.response = None
783 d = self.values.delete(
784 self.endpoint,
785 query=u'has fun/eating',
786 tags=[u'hey/you'])
787 self.assertEqual(1, self.endpoint.url.count('query='))
788 self.assertTrue(1, self.endpoint.url.count('query=has+fun%2Feating'))
789 return d
790
791
792 def testDeleteTagURIEncoding(self):
793 """
794 Check that the requested tag name is properly UTF-8 and %-encoded
795 in the request URI.
796 """
797 self.endpoint.response = None
798 d = self.values.delete(
799 self.endpoint,
800 query=u'has fun/eating',
801 tags=[u'hey/y \xF2 u'])
802 _, query = splitquery(self.endpoint.url)
803 args = query.split('&')
804 # Find the argument that starts with tag=
805 if args[0].startswith('tag='):
806 arg = args[0]
807 else:
808 arg = args[1]
809 value = arg.split('=')[1]
810 # The argument value should have its '/' %-encoded, the spaces
811 # converted to '+', and the %-encoded UTF-8 of the unicode
812 # \xF2 char.
813 self.assertEqual('hey%2Fy+%C3%B2+u', value)
814 return d
815
816
817 def testDeleteQueryURIEncoding(self):
818 """
819 Check that the requested query is properly UTF-8 and %-encoded in
820 the request URI.
821 """
822 response = {}
823 self.endpoint.response = json.dumps(response)
824 d = self.values.delete(
825 self.endpoint,
826 query=u'joe/blow = "embedded/slash with \xF1"',
827 tags=[u'hey/you'])
828 _, query = splitquery(self.endpoint.url)
829 args = query.split('&')
830 # Find the argument that starts with query=
831 if args[0].startswith('query='):
832 arg = args[0]
833 else:
834 arg = args[1]
835 value = arg.split('=')[1]
836 # The argument value should have the '/', '=' and '"' %-encoded,
837 # the spaces converted to '+', and the %-encoded UTF-8 of the
838 # unicode \xF1 char.
839 self.assertEqual('joe%2Fblow+%3D+%22embedded%2Fslash+with+%C3%B1%22',
840 value)
841 return d
842
843
626844
627class MockEndpoint(Endpoint):845class MockEndpoint(Endpoint):
628 """846 """

Subscribers

People subscribed via source and target branches

to all changes: