From ed116a71e3b3ad78a2f36a9c81075e70eeb24ddd Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Fri, 28 Sep 2012 19:14:14 +0000 Subject: Remove needless slots to speed up xapian index; index Implementation.version with preserving order --- diff --git a/doc/objects.dia b/doc/objects.dia index 2ec73f6..4da4476 100644 --- a/doc/objects.dia +++ b/doc/objects.dia @@ -90,7 +90,7 @@ - + @@ -99,7 +99,7 @@ - + #Context# @@ -197,7 +197,7 @@ #type# - #[enum] [R WN S F]# + #[enum] [R WN]# ## @@ -217,33 +217,10 @@ - #name# - - - #str [R WE S F]# - - - #""# - - - #Sugar Network name associated with the Context# - - - - - - - - - - - - - #implement# - #[str] [R WA F]# + #[str] [R WA]# #[]# @@ -473,7 +450,7 @@ #keep# - #bool [R W S L]# + #bool [R W L]# #False# @@ -496,7 +473,7 @@ #keep_impl# - #int [R W S L]# + #int [R W L]# #0# @@ -526,13 +503,13 @@ - + - + @@ -633,7 +610,7 @@ #guid# - #str [R S]# + #str [R]# ## @@ -702,7 +679,7 @@ #tags# - #[str] [R WA S F]# + #[str] [R WA F]# #[]# @@ -794,7 +771,7 @@ #location# - #str [R WA F S]# + #str [R WA F]# #""# @@ -847,13 +824,13 @@ - + - + @@ -954,7 +931,7 @@ #guid# - #str [R S]# + #str [R]# ## @@ -1023,7 +1000,7 @@ #user# - #[User] [R WA S]# + #[User] [R WA]# ## @@ -1069,7 +1046,7 @@ #layer# - #[enum] [R WA S F]# + #[enum] [R WA]# #[]# @@ -1092,7 +1069,7 @@ #tags# - #[str] [R WA S F]# + #[str] [R WA F]# #[]# @@ -1119,17 +1096,17 @@ - + - + - - + + @@ -1193,7 +1170,7 @@ - + @@ -1278,17 +1255,17 @@ - + - + - - + + @@ -1358,17 +1335,17 @@ - + - + - - + + @@ -1432,7 +1409,7 @@ - + @@ -1563,13 +1540,13 @@ - + - + @@ -1762,7 +1739,7 @@ #solution# - #Solution [R WA S]# + #Solution [R WA]# #""# @@ -1899,7 +1876,7 @@ #feedback# - #Feedback [R WN S]# + #Feedback [R WN]# ## @@ -1949,17 +1926,17 @@ - + - + - - + + @@ -2076,13 +2053,13 @@ - + - + @@ -2183,7 +2160,7 @@ #parent_resource# - #enum [R WN S]# + #enum [R WN]# ## @@ -2206,7 +2183,7 @@ #parent# - #guid [R WN S]# + #guid [R WN]# ## @@ -2366,7 +2343,7 @@ #type# - #enum [R WN S]# + #enum [R WN]# ## @@ -2389,7 +2366,7 @@ #resource# - #enum [R WN S]# + #enum [R WN]# #""# @@ -2412,7 +2389,7 @@ #object# - #str [R WN S]# + #str [R WN]# #""# @@ -2435,7 +2412,7 @@ #to# - #User [R WN S]# + #User [R WN]# #""# @@ -2662,7 +2639,7 @@ #keep# - #bool [R W S L]# + #bool [R W L]# #false# @@ -2708,7 +2685,7 @@ #title# - #str [R WA F I]# + #str [R WA S F I]# #""# @@ -2754,7 +2731,7 @@ #activity_id# - #str [R WA S]# + #str [R WA]# #""# @@ -3075,7 +3052,7 @@ #stability# - #enum [R WN S F]# + #enum [R WN F]# ## @@ -3151,13 +3128,13 @@ - + - + @@ -3258,7 +3235,7 @@ #context# - #guid [R WN S]# + #guid [R WN]# ## @@ -3281,7 +3258,7 @@ #implementation# - #Implementation [R WN S]# + #Implementation [R WN]# #""# @@ -3730,12 +3707,12 @@ - + - #[S] Property can be used in exact search and sorting# + #[S] Property can be sorted, grouped or searched by ranges# diff --git a/sugar_network/node/router.py b/sugar_network/node/router.py index 44aaf25..d51713e 100644 --- a/sugar_network/node/router.py +++ b/sugar_network/node/router.py @@ -55,7 +55,7 @@ class Router(router.Router): directory = self.commands.volume['context'] documents, total = directory.find(type='package', offset=request.get('offset'), limit=request.get('limit')) - return {'total': total.value, 'result': [i.guid for i in documents]} + return {'total': total, 'result': [i.guid for i in documents]} def _get_package(self, repo, package): directory = self.commands.volume['context'] diff --git a/sugar_network/resources/artifact.py b/sugar_network/resources/artifact.py index 8fd35b6..1adaa32 100644 --- a/sugar_network/resources/artifact.py +++ b/sugar_network/resources/artifact.py @@ -22,6 +22,9 @@ from sugar_network.resources.volume import Resource class Artifact(Resource): + # All properties are sloted to not fail on `get_uniquevaluesfor()` call + # while emulating sugar-datastore interface + @ad.active_property(slot=1, prefix='C', default='') def context(self, value): return value diff --git a/sugar_network/resources/context.py b/sugar_network/resources/context.py index 1745a82..5683664 100644 --- a/sugar_network/resources/context.py +++ b/sugar_network/resources/context.py @@ -31,11 +31,6 @@ class Context(Resource): def type(self, value): return value - @ad.active_property(slot=1, prefix='N', full_text=True, - permissions=ad.ACCESS_READ, default='') - def name(self, value): - return value - @ad.active_property(prefix='M', full_text=True, default=[], typecast=[]) def implement(self, value): @@ -136,6 +131,16 @@ class Context(Resource): return versions + @ad.active_property(ad.StoredProperty, typecast=[], default=[]) + def dependencies(self, value): + """Software dependencies. + + This is a transition method how to improve dependencies handling. + The regular way should be setting up them in activity.info instead. + + """ + return value + @ad.active_property(ad.StoredProperty, typecast=dict, default={}) def aliases(self, value): return value diff --git a/sugar_network/resources/feedback.py b/sugar_network/resources/feedback.py index 87f6b8a..e7309c0 100644 --- a/sugar_network/resources/feedback.py +++ b/sugar_network/resources/feedback.py @@ -39,6 +39,6 @@ class Feedback(Resource): def content(self, value): return value - @ad.active_property(slot=3, prefix='A', default='') + @ad.active_property(prefix='A', default='') def solution(self, value): return value diff --git a/sugar_network/resources/implementation.py b/sugar_network/resources/implementation.py index 1a6c3f1..b5dc774 100644 --- a/sugar_network/resources/implementation.py +++ b/sugar_network/resources/implementation.py @@ -19,9 +19,22 @@ import active_document as ad from sugar_network.zerosugar import GOOD_LICENSES from sugar_network import resources +from sugar_network.zerosugar import parse_version from sugar_network.resources.volume import Resource +def _encode_version(version): + result = '' + version = parse_version(version) + while version: + unit, modificator = version[:2] + del version[:2] + unit = ([0, 0] + unit)[-3:] + result += ''.join(['%05d' % i for i in unit]) + result += '%02d' % (10 + modificator) + return result + + class Implementation(Resource): @ad.active_property(prefix='C', @@ -34,17 +47,17 @@ class Implementation(Resource): def license(self, value): return value - @ad.active_property(slot=2, prefix='V', + @ad.active_property(slot=1, prefix='V', reprcast=_encode_version, permissions=ad.ACCESS_CREATE | ad.ACCESS_READ) def version(self, value): return value - @ad.active_property(slot=3, prefix='D', + @ad.active_property(slot=2, prefix='D', permissions=ad.ACCESS_CREATE | ad.ACCESS_READ, typecast=int) def date(self, value): return value - @ad.active_property(slot=4, prefix='S', full_text=True, + @ad.active_property(prefix='S', permissions=ad.ACCESS_CREATE | ad.ACCESS_READ, typecast=resources.STABILITIES) def stability(self, value): diff --git a/sugar_network/resources/notification.py b/sugar_network/resources/notification.py index f357b9c..4b78d75 100644 --- a/sugar_network/resources/notification.py +++ b/sugar_network/resources/notification.py @@ -21,24 +21,24 @@ from sugar_network.resources.volume import Resource class Notification(Resource): - @ad.active_property(slot=1, prefix='T', + @ad.active_property(prefix='T', permissions=ad.ACCESS_CREATE | ad.ACCESS_READ, typecast=resources.NOTIFICATION_TYPES) def type(self, value): return value - @ad.active_property(slot=2, prefix='K', + @ad.active_property(prefix='K', permissions=ad.ACCESS_CREATE | ad.ACCESS_READ, default='', typecast=resources.NOTIFICATION_OBJECT_TYPES) def resource(self, value): return value - @ad.active_property(slot=3, prefix='O', + @ad.active_property(prefix='O', permissions=ad.ACCESS_CREATE | ad.ACCESS_READ, default='') def object(self, value): return value - @ad.active_property(slot=4, prefix='D', + @ad.active_property(prefix='D', permissions=ad.ACCESS_CREATE | ad.ACCESS_READ, default='') def to(self, value): return value diff --git a/sugar_network/resources/user.py b/sugar_network/resources/user.py index 717888c..0c89c3a 100644 --- a/sugar_network/resources/user.py +++ b/sugar_network/resources/user.py @@ -32,11 +32,11 @@ class User(ad.Document): def color(self, value): return value - @ad.active_property(slot=3, prefix='S', permissions=ad.ACCESS_CREATE) + @ad.active_property(prefix='S', permissions=ad.ACCESS_CREATE) def machine_sn(self, value): return value - @ad.active_property(slot=4, prefix='U', permissions=ad.ACCESS_CREATE) + @ad.active_property(prefix='U', permissions=ad.ACCESS_CREATE) def machine_uuid(self, value): return value @@ -48,11 +48,11 @@ class User(ad.Document): def tags(self, value): return value - @ad.active_property(slot=5, prefix='P', full_text=True, default='') + @ad.active_property(prefix='P', full_text=True, default='') def location(self, value): return value - @ad.active_property(slot=6, prefix='B', default=0, typecast=int) + @ad.active_property(slot=2, prefix='B', default=0, typecast=int) def birthday(self, value): return value diff --git a/sugar_network/resources/volume.py b/sugar_network/resources/volume.py index 20dc90e..bf4fd70 100644 --- a/sugar_network/resources/volume.py +++ b/sugar_network/resources/volume.py @@ -154,7 +154,7 @@ class Commands(object): raise NotImplementedError() @ad.volume_command(method='GET', cmd='subscribe') - def subscribe(self, response, only_commits=False): + def subscribe(self, request, response, only_commits=False): """Subscribe to Server-Sent Events. :param only_commits: @@ -164,7 +164,10 @@ class Commands(object): """ response.content_type = 'text/event-stream' response['Cache-Control'] = 'no-cache' - return self._pull_events(only_commits) + peer = 'anonymous' + if hasattr(request, 'environ'): + peer = request.environ.get('HTTP_SUGAR_USER') or peer + return self._pull_events(peer, only_commits) @ad.directory_command_post(method='GET') def _Commands_find_post(self, request, response, result): @@ -196,22 +199,24 @@ class Commands(object): default='/'.join(['', document, guid, name]) + postfix, prefix=prefix) - def _pull_events(self, only_commits): + def _pull_events(self, peer, only_commits): + _logger.debug('Start pulling events to %s user', peer) # Otherwise, gevent's WSGI server doesn't sent HTTP status yield '\n' - while True: - event = self._notifier.get() - - if only_commits: - if event['event'] != 'commit': - continue - else: - if event['event'] == 'commit': - # Subscribers already got update notifications enough - continue - - yield 'data: %s\n\n' % json.dumps(event) + try: + while True: + event = self._notifier.get() + if only_commits: + if event['event'] != 'commit': + continue + else: + if event['event'] == 'commit': + # Subscribers already got update notifications enough + continue + yield 'data: %s\n\n' % json.dumps(event) + finally: + _logger.debug('Stop pulling events to %s user', peer) def _notify(self, event): self._notifier.set(event) diff --git a/tests/units/__main__.py b/tests/units/__main__.py index 19c72b7..da752b3 100644 --- a/tests/units/__main__.py +++ b/tests/units/__main__.py @@ -23,6 +23,7 @@ from node_mount import * from injector import * from mountset import * from context import * +from implementation import * from obs import * tests.main() diff --git a/tests/units/datastore.py b/tests/units/datastore.py index de1e67d..39e99da 100755 --- a/tests/units/datastore.py +++ b/tests/units/datastore.py @@ -23,12 +23,12 @@ class DatastoreTest(tests.Test): datastore.populate(artifacts) assert not exists(sn_stamp()) - self.assertEqual(0, artifacts.find()[1].value) + self.assertEqual(0, artifacts.find()[1]) self.touch(sn_stamp()) datastore.populate(artifacts) assert not exists(sn_stamp()) - self.assertEqual(0, artifacts.find()[1].value) + self.assertEqual(0, artifacts.find()[1]) self.touch(sn_stamp()) os.utime(sn_stamp(), (0, 0)) @@ -37,7 +37,7 @@ class DatastoreTest(tests.Test): datastore.populate(artifacts) assert exists(sn_stamp()) assert exists(ds_stamp()) - self.assertEqual(0, artifacts.find()[1].value) + self.assertEqual(0, artifacts.find()[1]) def test_populate(self): self.create_mountset([Artifact]) diff --git a/tests/units/implementation.py b/tests/units/implementation.py new file mode 100755 index 0000000..27b1397 --- /dev/null +++ b/tests/units/implementation.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +# sugar-lint: disable + +from __init__ import tests + +from sugar_network.resources.implementation import _encode_version + + +class ImplementationTest(tests.Test): + + def test_encode_version(self): + self.assertEqual( + '00000''00000''00001' '10', + _encode_version('1')) + self.assertEqual( + '00000''00001''00002' '10', + _encode_version('1.2')) + self.assertEqual( + '00001''00020''00300' '10', + _encode_version('1.20.300')) + self.assertEqual( + '00020''00300''04000' '10', + _encode_version('1.20.300.4000')) + + self.assertEqual( + '00000''00000''00001' '10' '00002''00003''00004' '10', + _encode_version('1-2.3.4')) + self.assertEqual( + '00000''00000''00001' '10' '00002''00003''00004' '10' '00006''00007''00008' '10', + _encode_version('1-2.3.4-5.6.7.8')) + + self.assertEqual( + '00000''00000''00001' '08', + _encode_version('1-pre')) + self.assertEqual( + '00000''00000''00001' '09', + _encode_version('1-rc')) + self.assertEqual( + '00000''00000''00001' '10', + _encode_version('1-')) + self.assertEqual( + '00000''00000''00001' '11', + _encode_version('1-post')) + + self.assertEqual( + '00000''00000''00001' '08' '00003''00004''00005' '10', + _encode_version('1-pre2.3.4.5')) + + +if __name__ == '__main__': + tests.main() diff --git a/tests/units/volume.py b/tests/units/volume.py index 0c43b67..23e3733 100755 --- a/tests/units/volume.py +++ b/tests/units/volume.py @@ -8,7 +8,7 @@ from __init__ import tests import active_document as ad from sugar_network.toolkit.collection import Sequence from sugar_network.toolkit.sneakernet import InPacket, OutBufferPacket, DiskFull -from sugar_network.resources.volume import Volume, Resource, Commands +from sugar_network.resources.volume import Volume, Resource, Commands, Request from active_toolkit import coroutine @@ -176,7 +176,7 @@ class VolumeTest(tests.Test): events = [] def read_events(): - for event in cp.subscribe(ad.Response()): + for event in cp.subscribe(Request(), ad.Response()): if not event.strip(): continue assert event.startswith('data: ') @@ -218,7 +218,7 @@ class VolumeTest(tests.Test): events = [] def read_events(): - for event in cp.subscribe(ad.Response(), only_commits=True): + for event in cp.subscribe(Request(), ad.Response(), only_commits=True): if not event.strip(): continue assert event.startswith('data: ') -- cgit v0.9.1