Browse files

Delete stuff that belongs to tgs-core

  • Loading branch information...
1 parent ba752c4 commit 3ddc693bf720e2e358a4b70783416aad32f5650a Elric Milon committed May 9, 2012
View
0 src/discovery/__init__.py
No changes.
View
492 src/discovery/community.py
@@ -1,492 +0,0 @@
-from itertools import islice, groupby
-from os import path, makedirs
-from random import sample, random
-
-from conversion import Conversion
-from payload import HotsPayload, SearchMemberRequestPayload, SearchSquareRequestPayload, SearchTextRequestPayload, SearchMemberResponsePayload, SearchSquareResponsePayload, SearchTextResponsePayload
-
-from square.community import PreviewCommunity
-from square.database import SquareDatabase
-
-from dispersy.authentication import NoAuthentication
-from dispersy.community import Community
-from dispersy.conversion import DefaultConversion
-from dispersy.destination import CommunityDestination, CandidateDestination
-from dispersy.distribution import DirectDistribution
-from dispersy.member import DummyMember
-from dispersy.message import Message, DropMessage
-from dispersy.requestcache import Cache
-from dispersy.resolution import PublicResolution
-
-if __debug__:
- from dispersy.dprint import dprint
-
-class Suggestion(object):
- def __init__(self, cid, mid, global_time):
- self.cid = cid
- self.mid = mid
- self.global_time = global_time
- self.attempt = 0
- self.sources = []
- self.state = "waiting"
- self.weight = 0
- self.square = None
- self.hit = None
-
- def __str__(self):
- return "<%s %s weight:%d id:%d %s:%s:%d>" % (self.__class__.__name__, self.state, self.weight, id(self), self.cid.encode("HEX"), self.mid.encode("HEX"), self.global_time)
-
- def _result(self, message, repository):
- if message and message.name == self.message_name:
- self.state = "done"
- self.hit = self.message_to_hit(message)
- self.square.dec_dependencies()
- if __debug__: dprint("hit! ", self, " (attempt #", self.attempt, ")")
- repository.on_hit()
- return True
-
- else:
- return False
-
- def _fetch_retry(self, response, repository):
- if not self._result(response, repository):
- if self.attempt < 10:
- self.attempt += 1
-
- # retry
- self.fetch(repository)
-
- else:
- self.state = "give-up"
- self.square.dec_dependencies()
-
- def fetch(self, repository):
- assert isinstance(repository, SuggestionRepository), type(repository)
- if self.state in ("waiting", "fetching"):
- if self.sources:
- assert self.hit is None
-
- if self.square is None:
- # get square
- try:
- self.square = repository.discovery.dispersy.get_community(self.cid, load=True)
- except KeyError:
- self.square = PreviewCommunity.join_community(DummyMember(self.cid), repository.discovery.my_member, repository.discovery, repository.enable_walker)
-
- if isinstance(self.square, PreviewCommunity) and repository.enable_walker and not self.square.dispersy_enable_candidate_walker:
- # we must enable the walker
- self.square.start_candidate_walker()
-
- self.state = "fetching"
- self.square.inc_dependencies()
-
- # get message
- source = self.sources[int(random() * len(self.sources))]
- if __debug__: dprint(self, " from ", source, " (attempt #", self.attempt, ")")
- message = self.square.fetch_message(self.mid, self.global_time, source, self._fetch_retry, (repository,), 5.0 if __debug__ else 1.0)
-
- self._result(message, repository)
-
- else:
- self.state = "waiting"
- self.square.dec_dependencies()
-
- @property
- def message_name(self):
- raise NotImplementedError()
-
- @property
- def message_to_hit(self):
- raise NotImplementedError()
-
-class MemberSuggestion(Suggestion):
- @property
- def message_name(self):
- return u"member-info"
-
- @property
- def message_to_hit(self):
- return self.square.message_to_member
-
-class SquareSuggestion(Suggestion):
- @property
- def message_name(self):
- return u"square-info"
-
- @property
- def message_to_hit(self):
- return lambda _: self.square
-
-class TextSuggestion(Suggestion):
- @property
- def message_name(self):
- return u"text"
-
- @property
- def message_to_hit(self):
- return self.square.message_to_text
-
-class HotSuggestion(TextSuggestion):
- pass
-
-class SuggestionRepository(object):
- def __init__(self, discovery):
- self.discovery = discovery
- self.unordered_suggestions = {}
- self.suggestions = []
-
- @property
- def enable_walker(self):
- raise NotImplementedError()
-
- def add_suggestions(self, source, suggestions, suggestion_cls):
- if __debug__: dprint(len(suggestions), " suggestions from ", source)
-
- for weight, cid, mid, global_time in suggestions:
- response = self.unordered_suggestions.get((cid, mid, global_time))
- if response is None:
- self.unordered_suggestions[(cid, mid, global_time)] = response = suggestion_cls(cid, mid, global_time)
-
- response.sources.append(source)
- response.weight += weight
-
- return len(self.unordered_suggestions) > len(self.suggestions)
-
- def order_and_fetch_suggestions(self, fetch_count):
- previous_suggestions_count = len(self.suggestions)
- previous_hit_count = sum(1 for suggestion in self.suggestions if suggestion.state == "done")
-
- # order by weight
- self.suggestions = sorted(self.unordered_suggestions.itervalues(), key=lambda response: response.weight, reverse=True)
-
- # download the top N hits
- for response in islice(self.suggestions, fetch_count):
- if response.state == "waiting":
- response.fetch(self)
-
- # returns True when we have new suggestions and no hits during the call to
- # order_and_fetch_suggestions
- return (len(self.suggestions) > previous_suggestions_count and
- sum(1 for suggestion in self.suggestions if suggestion.state == "done") == previous_hit_count)
-
-class HotCollector(SuggestionRepository):
- def __init__(self, discovery):
- super(HotCollector, self).__init__(discovery)
- self.top_squares = []
- self.top_texts = []
-
- @property
- def enable_walker(self):
- return True
-
- def on_hots(self, messages):
- for message in messages:
- self.add_suggestions(message.candidate, message.payload.suggestions, HotSuggestion)
-
- old_top = self.suggestions[:10]
- self.order_and_fetch_suggestions(10)
-
- for i, suggestion in enumerate(self.suggestions[:10]):
- suggestion.square.inc_dependencies()
-
- for suggestion in old_top:
- suggestion.square.dec_dependencies()
-
- def on_hit(self):
- self.top_texts = []
- self.top_squares = []
-
- for suggestion in self.suggestions:
- if suggestion.state == "done":
- if len(self.top_texts) < 10:
- self.top_texts.append(suggestion.hit)
-
- if len(self.top_squares) < 10:
- if not suggestion.square in self.top_squares:
- self.top_squares.append(suggestion.square)
- else:
- break
-
- if __debug__:
- for index, text in enumerate(self.top_texts):
- dprint("#", index, " - ", text)
- for index, square in enumerate(self.top_squares):
- dprint("#", index, " - ", square)
-
- # TODO notify GUI that there are new top squares and texts
-
-class SearchCache(SuggestionRepository, Cache):
- cleanup_delay = 180.0
-
- def __init__(self, discovery, terms, squares, threshold, response_func, response_args, timeout):
- super(SearchCache, self).__init__(discovery)
-
- # the original search request
- self.discovery = discovery
- self.terms = terms
- self.squares = squares
- self.threshold = threshold
- self.response_func = response_func
- self.response_args = response_args
- self.timeout_delay = timeout
-
- if __debug__: dprint("searching for ", terms)
-
- @property
- def enable_walker(self):
- return False
-
- def on_response(self, messages, suggestion_cls):
- for message in messages:
- self.add_suggestions(message.candidate, message.payload.suggestions, suggestion_cls)
-
- if self.order_and_fetch_suggestions(10):
- # inform that there are suggestions
- self.response_func(self, "suggestion", *self.response_args)
-
- def on_hit(self):
- # inform that there are suggestions
- self.response_func(self, "hit", *self.response_args)
-
- def on_timeout(self):
- # inform that there will be no more suggestions or hits
- self.response_func(self, "finished", *self.response_args)
-
-class DiscoveryCommunity(Community):
- def __init__(self, *args):
- self._explicitly_hot_text = []
- self._implicitly_hot_text = []
- self._hot_collector = HotCollector(self)
-
- super(DiscoveryCommunity, self).__init__(*args)
-
- self._database = SquareDatabase.has_instance()
- if not self._database:
- # our data storage
- sqlite_directory = path.join(self._dispersy.working_directory, u"sqlite")
- if not path.isdir(sqlite_directory):
- makedirs(sqlite_directory)
-
- self._database = SquareDatabase.get_instance(sqlite_directory)
- self._dispersy.database.attach_commit_callback(self._database.commit)
-
- self._pending_callbacks.append(self._dispersy.callback.register(self._select_and_announce_hot))
-
- def initiate_meta_messages(self):
- return [Message(self, u"hots", NoAuthentication(), PublicResolution(), DirectDistribution(), CommunityDestination(node_count=5), HotsPayload(), self._dispersy._generic_timeline_check, self._hot_collector.on_hots),
- Message(self, u"search-member-request", NoAuthentication(), PublicResolution(), DirectDistribution(), CommunityDestination(node_count=20), SearchMemberRequestPayload(), self._dispersy._generic_timeline_check, self.on_search_member_request),
- Message(self, u"search-square-request", NoAuthentication(), PublicResolution(), DirectDistribution(), CommunityDestination(node_count=20), SearchSquareRequestPayload(), self._dispersy._generic_timeline_check, self.on_search_square_request),
- Message(self, u"search-text-request", NoAuthentication(), PublicResolution(), DirectDistribution(), CommunityDestination(node_count=20), SearchTextRequestPayload(), self._dispersy._generic_timeline_check, self.on_search_text_request),
- Message(self, u"search-member-response", NoAuthentication(), PublicResolution(), DirectDistribution(), CandidateDestination(), SearchMemberResponsePayload(), self.check_search_response, self.on_search_member_response),
- Message(self, u"search-square-response", NoAuthentication(), PublicResolution(), DirectDistribution(), CandidateDestination(), SearchSquareResponsePayload(), self.check_search_response, self.on_search_square_response),
- Message(self, u"search-text-response", NoAuthentication(), PublicResolution(), DirectDistribution(), CandidateDestination(), SearchTextResponsePayload(), self.check_search_response, self.on_search_text_response)]
-
- def initiate_conversions(self):
- return [DefaultConversion(self), Conversion(self)]
-
- @property
- def top_squares(self):
- return self._hot_collector.top_squares
-
- @property
- def top_texts(self):
- return self._hot_collector.top_texts
-
- def add_explicitly_hot_text(self, message):
- # TODO all messages should be unique
- self._explicitly_hot_text.append(message)
- del self._explicitly_hot_text[20:]
-
- def add_implicitly_hot_text(self, messages):
- # TODO all messages should be unique
- self._implicitly_hot_text.extend(messages)
- del self._implicitly_hot_text[20:]
-
- def _select_and_announce_hot(self):
- meta = self._meta_messages[u"hots"]
- while True:
- # TODO yield 60.0, lowered for debugging
- yield 10.0
- # what is hot?
- # explicit: a message the user marked as 'hot'
- # implicit: a newly received message
- messages = sample(self._explicitly_hot_text, min(15, len(self._explicitly_hot_text)))
- messages.extend(sample(self._implicitly_hot_text, min(20-len(messages), len(self._implicitly_hot_text))))
- # TODO all messages should be unique
-
- if messages:
- if __debug__: dprint(len(messages), "x text")
- suggestions = [(0, message.community.cid, message.authentication.member.mid, message.distribution.global_time) for message in messages]
- message = meta.impl(distribution=(self.global_time,), payload=(suggestions,))
- # hots = [Hot(message.community.cid, message.authentication.member.mid, message.distribution.global_time) for message in messages]
- # message = meta.impl(distribution=(self.global_time,), payload=(hots,))
- self._dispersy.store_update_forward([message], False, False, True)
-
- def simple_member_search(self, string, response_func, response_args=(), timeout=10.0):
- pairs = [(min(len(keyword), 127), keyword) for keyword in string.split()]
- return self.member_search(pairs, [], 1, response_func, response_args, timeout)
-
- def simple_square_search(self, string, response_func, response_args=(), timeout=10.0):
- pairs = [(min(len(keyword), 127), keyword) for keyword in string.split()]
- return self.square_search(pairs, [], 1, response_func, response_args, timeout)
-
- def simple_text_search(self, string, response_func, response_args=(), timeout=10.0):
- pairs = [(min(len(keyword), 127), keyword) for keyword in string.split()]
- return self.text_search(pairs, [], 1, response_func, response_args, timeout)
-
- def member_search(self, terms, squares, threshold, response_func, response_args=(), timeout=10.0):
- cache = SearchCache(self, terms, squares, threshold, response_func, response_args, timeout)
- identifier = self._dispersy.request_cache.claim(cache)
-
- meta = self._meta_messages[u"search-member-request"]
- request = meta.impl(distribution=(self.global_time,), payload=(identifier, terms, squares, threshold))
- if not self._dispersy.store_update_forward([request], False, False, True):
- if __debug__: dprint("unable to search. most likely there are no candidates", level="warning")
- self._dispersy.request_cache.pop(identifier, SearchCache)
- cache.on_timeout()
-
- return cache
-
- def square_search(self, terms, squares, threshold, response_func, response_args=(), timeout=10.0):
- cache = SearchCache(self, terms, squares, threshold, response_func, response_args, timeout)
- identifier = self._dispersy.request_cache.claim(cache)
-
- meta = self._meta_messages[u"search-square-request"]
- request = meta.impl(distribution=(self.global_time,), payload=(identifier, terms, squares, threshold))
- if not self._dispersy.store_update_forward([request], False, False, True):
- if __debug__: dprint("unable to search. most likely there are no candidates", level="warning")
- self._dispersy.request_cache.pop(identifier, SearchCache)
- cache.on_timeout()
-
- return cache
-
- def text_search(self, terms, squares, threshold, response_func, response_args=(), timeout=10.0):
- cache = SearchCache(self, terms, squares, threshold, response_func, response_args, timeout)
- identifier = self._dispersy.request_cache.claim(cache)
-
- meta = self._meta_messages[u"search-text-request"]
- request = meta.impl(distribution=(self.global_time,), payload=(identifier, terms, squares, threshold))
- if not self._dispersy.store_update_forward([request], False, False, True):
- if __debug__: dprint("unable to search. most likely there are no candidates", level="warning")
- self._dispersy.request_cache.pop(identifier, SearchCache)
- cache.on_timeout()
-
- return cache
-
- def check_search_response(self, messages):
- for message in messages:
- if not self._dispersy.request_cache.has(message.payload.identifier, SearchCache):
- yield DropMessage(message, "invalid response identifier")
- continue
-
- yield message
-
- def on_search_member_response(self, messages):
- key = lambda message: message.payload.identifier
- for identifier, iterator in groupby(sorted(messages, key=key), key=key):
- cache = self._dispersy.request_cache.get(identifier, SearchCache)
- cache.on_response(list(iterator), MemberSuggestion)
-
- def on_search_square_response(self, messages):
- key = lambda message: message.payload.identifier
- for identifier, iterator in groupby(sorted(messages, key=key), key=key):
- cache = self._dispersy.request_cache.get(identifier, SearchCache)
- cache.on_response(list(iterator), SquareSuggestion)
-
- def on_search_text_response(self, messages):
- key = lambda message: message.payload.identifier
- for identifier, iterator in groupby(sorted(messages, key=key), key=key):
- cache = self._dispersy.request_cache.get(identifier, SearchCache)
- cache.on_response(list(iterator), TextSuggestion)
-
- def on_search_member_request(self, messages):
- execute = self._database.execute
- meta = self._meta_messages[u"search-member-response"]
- responses = []
-
- for message in messages:
- payload = message.payload
- if __debug__: dprint("searching ", " + ".join("%d:%s" % (weight, term) for weight, term in payload.terms), " for ", message.candidate)
-
- results = dict()
- for weight, term in payload.terms:
- for docid, in execute(u"SELECT docid FROM member_fts WHERE alias MATCH ?", (term,)):
- if docid in results:
- results[docid] += weight
- else:
- results[docid] = weight
-
- results = sorted(results.iteritems(), key=lambda tup:tup[1], reverse=True)
- suggestions = list(islice(self._sync_id_to_search_response(results), 21))
- if suggestions:
- responses.append(meta.impl(distribution=(self.global_time,), destination=(message.candidate,), payload=(payload.identifier, suggestions)))
-
- if responses:
- self._dispersy.store_update_forward(responses, False, False, True)
-
- def on_search_square_request(self, messages):
- execute = self._database.execute
- meta = self._meta_messages[u"search-square-response"]
- responses = []
-
- for message in messages:
- payload = message.payload
- if __debug__: dprint("searching ", " + ".join("%d:%s" % (weight, term) for weight, term in payload.terms), " for ", message.candidate)
-
- results = dict()
- for weight, term in payload.terms:
- for docid, in execute(u"SELECT docid FROM square_fts WHERE title MATCH ?", (term,)):
- if docid in results:
- results[docid] += weight
- else:
- results[docid] = weight
-
- for docid, in execute(u"SELECT docid FROM square_fts WHERE description MATCH ?", (term,)):
- if docid in results:
- results[docid] += weight
- else:
- results[docid] = weight
-
- results = sorted(results.iteritems(), key=lambda tup:tup[1], reverse=True)
- suggestions = list(islice(self._sync_id_to_search_response(results), 21))
- if suggestions:
- responses.append(meta.impl(distribution=(self.global_time,), destination=(message.candidate,), payload=(payload.identifier, suggestions)))
-
- self._dispersy.store_update_forward(responses, False, False, True)
-
- def on_search_text_request(self, messages):
- execute = self._database.execute
- meta = self._meta_messages[u"search-text-response"]
- responses = []
-
- for message in messages:
- payload = message.payload
- if __debug__: dprint("searching ", " + ".join("%d:%s" % (weight, term) for weight, term in payload.terms), " for ", message.candidate)
-
- results = dict()
- for weight, term in payload.terms:
- for docid, in execute(u"SELECT docid FROM text_fts WHERE text MATCH ?", (term,)):
- if docid in results:
- results[docid] += weight
- else:
- results[docid] = weight
-
- results = sorted(results.iteritems(), key=lambda tup:tup[1], reverse=True)
- suggestions = list(islice(self._sync_id_to_search_response(results), 20))
- if suggestions:
- responses.append(meta.impl(distribution=(self.global_time,), destination=(message.candidate,), payload=(payload.identifier, suggestions,)))
-
- if responses:
- self._dispersy.store_update_forward(responses, False, False, True)
-
- def _sync_id_to_search_response(self, results):
- dispersy_execute = self._dispersy.database.execute
- for docid, weight in results:
- try:
- cid, mid, global_time = dispersy_execute(u"SELECT master.mid, member.mid, sync.global_time FROM sync JOIN community ON community.id = sync.community JOIN member AS master ON master.id = community.master JOIN member ON member.id = sync.member WHERE sync.id = ?", (docid,)).next()
- except StopIteration:
- if __debug__: dprint("unable to determine results for docid ", docid, level="error")
- continue
- else:
- yield weight, str(cid), str(mid), global_time
-
View
110 src/discovery/conversion.py
@@ -1,110 +0,0 @@
-from struct import pack, unpack_from
-
-from dispersy.conversion import BinaryConversion
-from dispersy.message import DropPacket
-
-class Conversion(BinaryConversion):
- def __init__(self, community):
- super(Conversion, self).__init__(community, "\x01")
- self.define_meta_message(chr(1), community.get_meta_message(u"hots"), self._encode_hots, self._decode_hots)
- self.define_meta_message(chr(2), community.get_meta_message(u"search-member-request"), self._encode_search_request, self._decode_search_request)
- self.define_meta_message(chr(3), community.get_meta_message(u"search-member-response"), self._encode_search_response, self._decode_search_response)
- self.define_meta_message(chr(4), community.get_meta_message(u"search-square-request"), self._encode_search_request, self._decode_search_request)
- self.define_meta_message(chr(5), community.get_meta_message(u"search-square-response"), self._encode_search_response, self._decode_search_response)
- self.define_meta_message(chr(6), community.get_meta_message(u"search-text-request"), self._encode_search_request, self._decode_search_request)
- self.define_meta_message(chr(7), community.get_meta_message(u"search-text-response"), self._encode_search_response, self._decode_search_response)
-
- def _encode_hots(self, message):
- data = [pack("!B", len(message.payload.suggestions))]
- for weight, cid, mid, global_time in message.payload.suggestions:
- data.append(pack("!B20s20sQ", weight, cid, mid, global_time))
- return data
-
- def _decode_hots(self, placeholder, offset, data):
- if len(data) < offset + 1:
- raise DropPacket("Insufficient packet size")
- count, = unpack_from("!B", data, offset)
- offset += 1
-
- suggestions = []
- for _ in xrange(count):
- if len(data) < offset + 49:
- raise DropPacket("Insufficient packet size")
- suggestions.append(unpack_from("!B20s20sQ", data, offset))
- offset += 49
-
- if not suggestions:
- raise DropPacket("no suggestions found")
-
- return offset, placeholder.meta.payload.implement(suggestions)
-
- def _encode_search_request(self, message):
- payload = message.payload
- data = [pack("!HBB", payload.identifier, payload.threshold, len(payload.terms))]
- for weight, term in payload.terms:
- term = term.encode("UTF-8")
- data.append(pack("!bB", weight, len(term)))
- data.append(term)
- data.append(pack("!B", len(payload.squares)))
- for weight, cid in payload.squares:
- data.append(pack("!b20s", weight, cid))
- return data
-
- def _decode_search_request(self, placeholder, offset, data):
- if len(data) < offset + 4:
- raise DropPacket("Insufficient packet size")
- identifier, threshold, term_length = unpack_from("!HBB", data, offset)
- offset += 4
-
- terms = []
- for _ in xrange(term_length):
- if len(data) < offset + 2:
- raise DropPacket("Insufficient packet size")
- weight, term_length = unpack_from("!bB", data, offset)
- offset += 2
-
- if len(data) < offset + term_length:
- raise DropPacket("Insufficient packet size")
- try:
- term = data[offset:offset+term_length].decode("UTF-8")
- except UnicodeError:
- raise DropPacket("Unable to decode UTF-8")
- offset += term_length
-
- terms.append((weight, term))
-
- if len(data) < offset + 1:
- raise DropPacket("Insufficient packet size")
- square_length, = unpack_from("!B", data, offset)
- offset += 1
-
- squares = []
- for _ in xrange(square_length):
- if len(data) < offset + 21:
- raise DropPacket("Insufficient packet size")
- squares.append(unpack_from("!b20s", data, offset))
- offset += 21
-
- return offset, placeholder.meta.payload.implement(identifier, terms, squares, threshold)
-
- def _encode_search_response(self, message):
- payload = message.payload
- data = [pack("!HB", payload.identifier, len(payload.suggestions))]
- for weight, cid, mid, global_time in payload.suggestions:
- data.append(pack("!B20s20sQ", weight, cid, mid, global_time))
- return data
-
- def _decode_search_response(self, placeholder, offset, data):
- if len(data) < offset + 3:
- raise DropPacket("Insufficient packet size")
- identifier, count = unpack_from("!HB", data, offset)
- offset += 3
-
- suggestions = []
- for _ in xrange(count):
- if len(data) < offset + 49:
- raise DropPacket("Insufficient packet size")
- suggestions.append(unpack_from("!B20s20sQ", data, offset))
- offset += 49
-
- return offset, placeholder.meta.payload.implement(identifier, suggestions)
View
73 src/discovery/payload.py
@@ -1,73 +0,0 @@
-from dispersy.payload import Payload
-
-class HotsPayload(Payload):
- class Implementation(Payload.Implementation):
- def __init__(self, meta, suggestions):
- """
- Implement hots message.
-
- SUGGESTIONS is a list containing (weight, community-id, member-id, global-time) quadruples.
- """
- super(HotsPayload.Implementation, self).__init__(meta)
- self._suggestions = suggestions
-
- @property
- def suggestions(self):
- return self._suggestions
-
-class SearchRequestPayload(Payload):
- class Implementation(Payload.Implementation):
- def __init__(self, meta, identifier, terms, squares, threshold):
- """
- Implement search request.
-
- IDENTIFIER is a 2 byte number.
- TERMS is a list containing (weight, string) pairs.
- SQUARES is a list containing (weight, community-id) pairs.
- THRESHOLD is the minimal value for a hit to qualify.
- """
- assert isinstance(terms, list) and 0 < len(terms) < 256
- assert all(isinstance(x, tuple) and len(x) == 2 for x in terms)
- assert all(isinstance(x[0], int) and -128 <= x[0] < 128 for x in terms)
- assert all(isinstance(x[1], unicode) and len(x[1].encode("UTF-8")) < 256 for x in terms)
- assert isinstance(squares, list) and len(squares) < 256
- assert all(isinstance(x, tuple) and len(x) == 2 for x in squares)
- assert all(isinstance(x[0], int) and -128 <= x[0] < 128 for x in squares)
- assert all(isinstance(x[1], unicode) and len(x[1]) == 20 for x in squares)
- assert isinstance(threshold, int) and 0 < threshold < 256
- super(SearchRequestPayload.Implementation, self).__init__(meta)
- self.identifier = identifier
- self.terms = terms
- self.squares = squares
- self.threshold = threshold
-
-class SearchMemberRequestPayload(SearchRequestPayload):
- pass
-
-class SearchSquareRequestPayload(SearchRequestPayload):
- pass
-
-class SearchTextRequestPayload(SearchRequestPayload):
- pass
-
-class SearchResponsePayload(Payload):
- class Implementation(Payload.Implementation):
- def __init__(self, meta, identifier, suggestions):
- """
- Implement search response.
-
- IDENTIFIER is a 2 byte number.
- SUGGESTIONS is a list containing (weight, community-id, member-id, global-time) quadruples.
- """
- super(SearchResponsePayload.Implementation, self).__init__(meta)
- self.identifier = identifier
- self.suggestions = suggestions
-
-class SearchMemberResponsePayload(SearchResponsePayload):
- pass
-
-class SearchSquareResponsePayload(SearchResponsePayload):
- pass
-
-class SearchTextResponsePayload(SearchResponsePayload):
- pass
View
16 src/discovery/script.py
@@ -1,16 +0,0 @@
-"""
-Example file
-
-python Tribler/Main/dispersy.py --script template
-"""
-
-from dispersy.dprint import dprint
-from dispersy.script import ScriptBase
-
-class TestScript(ScriptBase):
- def run(self):
- self.caller(self.test)
-
- def test(self):
- dprint("testing...")
- assert True
View
9 src/events/__init__.py
@@ -1,9 +0,0 @@
-
-from main import *
-
-import qt
-
-try:
- import qt
-except ImportError:
- print "Could not import qt event module."
View
18 src/events/dummy.py
@@ -1,18 +0,0 @@
-
-class DummyEventBroker(object):
- """
- A dummy event broker that just prints the events it receives.
- """
- class DummyPrinter:
- def __init__(self, event):
- self._event_name=event
-
- def __call__(self, *argv, **kwargs):
- print "Event: %s fired with %s %s" % (self._event_name, argv, kwargs)
-
- def __getattr__(self, attr):
- return self.DummyPrinter(attr)
-
-def getDummyEventBroker(obj):
- return DummyEventBroker()
-
View
14 src/events/main.py
@@ -1,14 +0,0 @@
-
-from dummy import getDummyEventBroker
-
-__all__=('setEventBrokerFactory', 'getEventBroker')
-
-EVENT_BROKER_FACTORY=getDummyEventBroker
-
-def setEventBrokerFactory(factory):
- global EVENT_BROKER_FACTORY
- EVENT_BROKER_FACTORY=factory
-
-def getEventBroker(obj):
- return EVENT_BROKER_FACTORY(obj)
-
View
52 src/events/qt.py
@@ -1,52 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-
-from PyQt4.QtCore import QObject, SIGNAL, pyqtSignal
-
-from square.community import SquareCommunity, PreviewCommunity
-
-_global_broker = None
-
-def createEventBroker(obj):
- if obj == None:
- global _global_broker
- if not _global_broker:
- _global_broker = QtGlobalEventBroker()
- return _global_broker
- else:
- return QtEventBroker(obj)
-
-class QtEventBroker(QObject):
- def __init__(self, obj):
- super(QtEventBroker, self).__init__()
- self._obj = obj
-
- class QtEmitter:
- def __init__(self, broker, event):
- self._broker=broker
- self._event_name=event
-
- def __call__(self, *argv):
- #print "EventQT: %s fired with %s" % (self._event_name, argv)
- if argv:
- self._broker.emit(SIGNAL(self._event_name), *argv)
- else:
- self._broker.emit(SIGNAL(self._event_name))
-
- def __getattr__(self, attr):
- #TODO: Cache instances so we don't create objects for the same signals more than once.
- return self.QtEmitter(self, attr)
-
-class QtGlobalEventBroker:
- def __init__(self):
- self.qt = QtGlobalEventBrokerWrapped()
-
- #TODO: use __gettattr__ for this.
- def newCommunityCreated(self, square):
- self.qt.newCommunityCreated.emit(square)
- def newPreviewCommunityCreated(self, square):
- self.qt.newPreviewCommunityCreated.emit(square)
-
-class QtGlobalEventBrokerWrapped(QObject):
- newCommunityCreated = pyqtSignal(SquareCommunity)
- newPreviewCommunityCreated = pyqtSignal(PreviewCommunity)
View
0 src/square/__init__.py
No changes.
View
466 src/square/community.py
@@ -1,466 +0,0 @@
-from os import path, makedirs
-from sys import maxsize
-
-from conversion import Conversion
-from database import SquareDatabase
-from payload import MemberInfoPayload, SquareInfoPayload, TextPayload
-from state import DummyState, UnknownState, SquareState, TaskGroupState
-
-from dispersy.authentication import MemberAuthentication
-from dispersy.community import Community
-from dispersy.conversion import DefaultConversion
-from dispersy.destination import CommunityDestination
-from dispersy.dispersy import MissingMessageCache, MissingLastMessageCache, CANDIDATE_WALKER_CALLBACK_ID
-from dispersy.distribution import FullSyncDistribution, LastSyncDistribution
-from dispersy.member import DummyMember
-from dispersy.message import Message
-from dispersy.resolution import DynamicResolution, PublicResolution, LinearResolution
-if __debug__:
- from dispersy.dprint import dprint
-
-class Member(object):
- __slots__ = ["square", "sync_id", "member_id", "alias", "thumbnail_hash"]
-
- def __init__(self, square, sync_id, member_id, alias, thumbnail_hash):
- assert isinstance(square, SquareBase)
- assert isinstance(sync_id, (int, long))
- assert isinstance(member_id, (int, long))
- assert isinstance(alias, unicode)
- assert isinstance(thumbnail_hash, str)
- self.square = square
- self.sync_id = sync_id
- self.member_id = member_id
- self.alias = alias
- self.thumbnail_hash = thumbnail_hash
-
- def __str__(self):
- return "<Member %d: %s>" % (self.sync_id, self.alias)
-
-class Text(object):
- __slots__ = ["square", "member", "sync_id", "global_time", "text", "media_hash", "utc_timestamp"]
-
- def __init__(self, square, member, sync_id, global_time, text, media_hash, utc_timestamp):
- assert isinstance(square, SquareBase)
- assert isinstance(member, Member)
- assert isinstance(sync_id, (int, long))
- assert isinstance(global_time, (int, long))
- assert isinstance(text, unicode)
- assert isinstance(media_hash, str)
- assert isinstance(utc_timestamp, (int, long))
- self.square = square
- self.member = member
- self.sync_id = sync_id
- self.global_time = global_time
- self.text = text
- self.media_hash = media_hash
- self.utc_timestamp = utc_timestamp
-
- def __str__(self):
- return "<Text %d: %s>" % (self.sync_id, self.text)
-
-class SquareBase(Community):
- def __init__(self, master, discovery):
- self._state = DummyState()
- super(SquareBase, self).__init__(master)
-
- self._database = SquareDatabase.has_instance()
- if not self._database:
- # our data storage
- sqlite_directory = path.join(self._dispersy.working_directory, u"sqlite")
- if not path.isdir(sqlite_directory):
- makedirs(sqlite_directory)
-
- self._database = SquareDatabase.get_instance(sqlite_directory)
- self._dispersy.database.attach_commit_callback(self._database.commit)
-
- self._discovery = discovery
- self._my_member_info = self._dispersy.get_last_message(self, self._my_member, self._meta_messages[u"member-info"])
-
- # get square info from self._database_id
- try:
- self._update_global_time, self._title, self._description, thumbnail_hash = self._database.execute(u"SELECT global_time, title, description, thumbnail_hash FROM square JOIN square_fts ON docid = sync_id WHERE square_id = ?", (self._database_id,)).next()
- self._thumbnail_hash = str(thumbnail_hash)
- except StopIteration:
- self._update_global_time = 0
- self._title = u""
- self._description = u""
- self._thumbnail_hash = ""
-
- # get my member info from self._database_id and self._my_member.database_id
- try:
- self._my_alias, my_thumbnail_hash = self._database.execute(u"SELECT alias, thumbnail_hash FROM member JOIN member_fts ON docid = sync_id WHERE member_id = ? AND square_id = ?", (self._my_member.database_id, self._database_id)).next()
- self._my_thumbnail_hash = str(my_thumbnail_hash)
- except StopIteration:
- self._my_alias = u"Anonymous"
- self._my_thumbnail_hash = ""
-
- self._dependencies = 0
-
- if __debug__: dprint("new Square '", self._title, "' using alias '", self._my_alias, "'")
-
- self.events = getEventBroker(self)
- self.global_events = getEventBroker(None)
-
- def load_history():
- sql = u"""
-SELECT text.sync_id, text_fts.text, text.media_hash, text.utc_timestamp, text.global_time, member.sync_id, member.member_id, member_fts.alias, member.thumbnail_hash
-FROM text
-JOIN text_fts ON text_fts.docid = text.sync_id
-JOIN member ON member.member_id = text.member_id
-JOIN member_fts ON member_fts.docid = member.sync_id
-WHERE text.square_id = ?
-ORDER BY text.global_time, text.utc_timestamp DESC
-LIMIT 100"""
-
- member_id = global_time = 0
- for text_sync_id, text, media_hash, utc_timestamp, global_time, member_sync_id, member_id, member_alias, member_thumbnail_hash in self._database.execute(sql, (self._database_id,)):
- member = Member(self, member_sync_id, member_id, member_alias, str(member_thumbnail_hash))
- text = Text(self, member, text_sync_id, global_time, text, str(media_hash), utc_timestamp)
- if __debug__: dprint(text)
- self.events.messageReceived(text)
-
- if member_id and global_time:
- # use one message to implicitly announce this square
- try:
- packet, = self._dispersy.database.execute(u"SELECT packet FROM sync WHERE community = ? AND member = ? AND global_time = ?",
- (self._database_id, member_id, global_time)).next()
- except StopIteration:
- pass
- else:
- message = self._dispersy.convert_packet_to_message(str(packet), self)
- self._discovery.add_implicitly_hot_text([message])
-
- self._dispersy.callback.register(load_history, delay=1.0)
-
- def initiate_meta_messages(self):
- return [Message(self, u"member-info", MemberAuthentication(encoding="sha1"), DynamicResolution(PublicResolution(), LinearResolution()), LastSyncDistribution(synchronization_direction=u"ASC", priority=16, history_size=1), CommunityDestination(node_count=0), MemberInfoPayload(), self._dispersy._generic_timeline_check, self.on_member_info, self.undo_member_info),
- Message(self, u"square-info", MemberAuthentication(encoding="sha1"), DynamicResolution(PublicResolution(), LinearResolution()), LastSyncDistribution(synchronization_direction=u"ASC", priority=128, history_size=1), CommunityDestination(node_count=10), SquareInfoPayload(), self._dispersy._generic_timeline_check, self.on_square_info, self.undo_square_info),
- Message(self, u"text", MemberAuthentication(encoding="sha1"), DynamicResolution(PublicResolution(), LinearResolution()), FullSyncDistribution(enable_sequence_number=False, synchronization_direction=u"DESC", priority=128), CommunityDestination(node_count=10), TextPayload(), self._dispersy._generic_timeline_check, self.on_text, self.undo_text)]
-
- def initiate_conversions(self):
- return [DefaultConversion(self), Conversion(self)]
-
- @property
- def title(self):
- return self._title
-
- @property
- def description(self):
- return self._description
-
- @property
- def thumbnail_hash(self):
- return self._thumbnail_hash
-
- @property
- def location(self):
- return (0, 0)
-
- @property
- def radius(self):
- return 0
-
- @property
- def allowed_to_set_member_info(self):
- allowed, _ = self._timeline.allowed(self._meta_messages[u"member-info"], self.global_time + 1)
- return allowed
-
- @property
- def allowed_to_set_square_info(self):
- allowed, _ = self._timeline.allowed(self._meta_messages[u"square-info"], self.global_time + 1)
- return allowed
-
- @property
- def allowed_to_post_message(self):
- allowed, _ = self._timeline.allowed(self._meta_messages[u"text"], self.global_time + 1)
- return allowed
-
- def dispersy_on_dynamic_settings(self, messages, initializing=False):
- super(SquareBase, self).dispersy_on_dynamic_settings(messages, initializing)
-
- global_time = self.global_time + 1
- policies = []
- for name in [u"member-info", u"square-info", u"text"]:
- meta = self._meta_messages[name]
- policy, _ = self._timeline.get_resolution_policy(meta, global_time)
- policies.append(policy)
-
- if all(isinstance(policy, PublicResolution) for policy in policies):
- self._state = SquareState(self._state)
- elif all(isinstance(policy, LinearResolution) for policy in policies):
- self._state = TaskGroupState(self._state)
- else:
- self._state = UnknownState(self._state)
-
- def convert_to_task_group(self):
- # TODO this check should be done in dispersy.py
- meta = self._meta_messages[u"dispersy-dynamic-settings"]
- if not self._timeline.allowed(meta, self.global_time + 1)[0]:
- raise ValueError("not allowed")
- policies = []
- for name in [u"member-info", u"square-info", u"text"]:
- meta = self._meta_messages[name]
- policies.append((meta, meta.resolution.policies[1]))
- self._dispersy.create_dynamic_settings(self, policies)
- self._dispersy.reclassify_community(self, TaskGroup)
-
- def set_my_member_info(self, name, thumbnail_hash):
- if not (isinstance(name, unicode) and len(name.encode("UTF-8")) < 256):
- raise ValueError("invalid name")
- if not (isinstance(thumbnail_hash, str) and len(thumbnail_hash) in (0, 20)):
- raise ValueError("invalid thumbnail hash")
- meta = self._meta_messages[u"member-info"]
- if not self._timeline.allowed(meta, self.global_time + 1)[0]:
- raise ValueError("not allowed")
- global_time = self.claim_global_time()
- policy, _ = self._timeline.get_resolution_policy(meta, global_time)
- self._my_member_info = meta.impl(authentication=(self._my_member,),
- resolution=(policy.implement(),),
- distribution=(global_time,),
- payload=(name, thumbnail_hash))
- self._dispersy.store_update_forward([self._my_member_info], True, True, True)
- return self._my_member_info
-
- def on_member_info(self, messages):
- data = []
- data_fts = []
-
- for message in messages:
- member = self.message_to_member(message)
- if __debug__: dprint("member #", member.member_id, ": ", member.alias)
-
- # database data
- data.append((member.sync_id, member.member_id, self._database_id, buffer(member.thumbnail_hash)))
- data_fts.append((member.sync_id, member.alias))
-
- if member.member_id == self._my_member.database_id:
- self._my_alias = member.alias
- self._my_thumbnail_hash = member.thumbnail_hash
-
- self.events.memberInfoUpdated(member)
-
- self._database.executemany(u"INSERT OR REPLACE INTO member (sync_id, member_id, square_id, thumbnail_hash) VALUES (?, ?, ?, ?)", data)
- self._database.executemany(u"INSERT OR REPLACE INTO member_fts (docid, alias) VALUES (?, ?)", data_fts)
-
- # this might be a response to a dispersy-missing-message
- self._dispersy.handle_missing_messages(messages, MissingLastMessageCache)
- self._dispersy.handle_missing_messages(messages, MissingMessageCache)
-
- def undo_member_info(self, *args):
- pass
-
- def set_square_info(self, title, description, thumbnail_hash, location, radius):
- if not (isinstance(title, unicode) and len(title.encode("UTF-8")) < 256):
- raise ValueError("invalid title")
- if not (isinstance(description, unicode) and len(description.encode("UTF-8")) < 1024):
- raise ValueError("invalid description")
- if not (isinstance(thumbnail_hash, str) and len(thumbnail_hash) in (0, 20)):
- raise ValueError("invalid thumbnail hash")
- if not (isinstance(location, tuple) and len(location) == 2 and isinstance(location[0], int) and isinstance(location[1], int)):
- raise ValueError("invalid location")
- if not (isinstance(radius, int) and 0 <= radius):
- raise ValueError("invalid radius")
- meta = self._meta_messages[u"square-info"]
- if not self._timeline.allowed(meta, self.global_time + 1)[0]:
- raise ValueError("not allowed")
- global_time = self.claim_global_time()
- policy, _ = self._timeline.get_resolution_policy(meta, global_time)
- message = meta.impl(authentication=(self._my_member,),
- resolution=(policy.implement(),),
- distribution=(self.claim_global_time(),),
- payload=(title, description, thumbnail_hash, location, radius))
- self._dispersy.store_update_forward([message], True, True, True)
- return message
-
- def on_square_info(self, messages):
- update = False
- for message in messages:
- # because LastSyncDistribution works per member we will need to keep the most recent
- if message.distribution.global_time > self._update_global_time:
- self._update_global_time = message.distribution.global_time
- self._title = message.payload.title
- self._description = message.payload.description
- self._thumbnail_hash = message.payload.thumbnail_hash
- self._database.execute(u"INSERT OR REPLACE INTO square (sync_id, square_id, global_time, thumbnail_hash) VALUES (?, ?, ?, ?)", (message.packet_id, self._database_id, self._update_global_time, buffer(self._thumbnail_hash)))
- self._database.execute(u"INSERT OR REPLACE INTO square_fts (docid, title, description) VALUES (?, ?, ?)", (message.packet_id, self._title, self._description))
- update = True
-
- if update:
- if __debug__: dprint("square ", self._title)
- # update GUI: square info has changed
- self.events.squareInfoUpdated()
-
- # this might be a response to a dispersy-missing-message
- self._dispersy.handle_missing_messages(messages, MissingMessageCache)
-
- def undo_square_info(self, *args):
- pass
-
- def post_text(self, text, media_hash):
- if self._my_member_info is None:
- self.set_my_member_info(self._my_alias, self._my_thumbnail_hash)
- if not (isinstance(text, unicode) and len(text.encode("UTF-8")) < 1024):
- raise ValueError("invalid text")
- if not (isinstance(media_hash, str) and len(media_hash) in (0, 20)):
- raise ValueError("invalid media hash")
- meta = self._meta_messages[u"text"]
- if not self._timeline.allowed(meta, self.global_time + 1)[0]:
- raise ValueError("not allowed")
- global_time = self.claim_global_time()
- policy, _ = self._timeline.get_resolution_policy(meta, global_time)
- message = meta.impl(authentication=(self._my_member,),
- resolution=(policy.implement(),),
- distribution=(self.claim_global_time(),),
- payload=(self._my_member_info, text, media_hash, "now"))
- self._dispersy.store_update_forward([message], True, True, True)
- return message
-
- def on_text(self, messages, mark_as_hot=True):
- data = []
- data_fts = []
-
- for message in messages:
- text = self.message_to_text(message)
- if __debug__: dprint("text ", text.member.alias, " says ", text.text)
-
- # database data
- data.append((text.sync_id, self._database_id, text.member.member_id, text.global_time, buffer(text.media_hash), text.utc_timestamp))
- data_fts.append((text.sync_id, text.text))
-
- # update GUI: message has been received
- self.events.messageReceived(text)
-
- self._database.executemany(u"INSERT INTO text (sync_id, square_id, member_id, global_time, media_hash, utc_timestamp) VALUES (?, ?, ?, ?, ?, ?)", data)
- self._database.executemany(u"INSERT INTO text_fts (docid, text) VALUES (?, ?)", data_fts)
-
- if mark_as_hot:
- self._discovery.add_implicitly_hot_text(messages)
-
- # this might be a response to a dispersy-missing-message
- self._dispersy.handle_missing_messages(messages, MissingMessageCache)
-
- def message_to_member(self, message):
- assert message.name == u"member-info"
- return Member(self, message.packet_id, message.authentication.member.database_id, message.payload.alias, message.payload.thumbnail_hash)
-
- def message_to_text(self, message):
- assert message.name == u"text"
- return Text(self, self.message_to_member(message.payload.member_info), message.packet_id, message.distribution.global_time, message.payload.text, message.payload.media_hash, message.payload.utc_timestamp)
-
- def undo_text(self, *args):
- pass
-
- def fetch_message(self, mid, global_time, source, response_func=None, response_args=(), timeout=10.0):
- members = self._dispersy.get_members_from_id(mid)
- if members:
- for member in members:
- message = self._dispersy.get_message(self, member, global_time)
- if message:
- if __debug__: dprint("message found")
- return message
-
- else:
- if __debug__: dprint("fetching message")
- self._dispersy.create_missing_message_newstyle(self, source, member, global_time, response_func, response_args, timeout)
-
- else:
- if __debug__: dprint("fetching identity")
- self._dispersy.create_missing_identity(self, source, DummyMember(mid), response_func, response_args, timeout)
-
- # TODO remove fetch_hot_text
- def fetch_hot_text(self, hot):
- members = self._dispersy.get_members_from_id(hot.mid)
- if members:
- for member in members:
- message = self._dispersy.get_message(self, member, hot.global_time)
- if message:
- return message
- else:
- candidate = hot.sources.pop(0)
- self._dispersy.create_missing_message(self, candidate, member, hot.global_time)
-
- else:
- self._dispersy.create_missing_identity(self, hot.sources[0], DummyMember(hot.mid))
-
-
- def has_dependencies(self):
- return self._dependencies > 0
-
- def inc_dependencies(self):
- self._dependencies += 1
-
- def dec_dependencies(self):
- self._dependencies -= 1
-
- def __str__(self):
- return "<%s %s>" % (self.__class__.__name__, self.title)
-
-class SquareCommunity(SquareBase):
- def __init__(self, *argv, **kwargs):
- super(SquareCommunity, self).__init__(*argv, **kwargs)
-
- #Notify about new square creation
- self.global_events.newCommunityCreated(self)
-
- def leave_square(self):
- return self._dispersy.reclassify_community(self, PreviewCommunity)
-
-class PreviewCommunity(SquareBase):
- def __init__(self, master, discovery, enable_walker):
- assert isinstance(enable_walker, bool)
-
- # set before calling super
- self._enable_walker = enable_walker
-
- super(PreviewCommunity, self).__init__(master, discovery)
- self._auto_unload_identifier = "auto-unload-preview-community-%s" % self._cid.encode("HEX")
- self._pending_callbacks.append(self._auto_unload_identifier)
-
- #Notify about new square creation
- self.global_events.newPreviewCommunityCreated(self)
-
- def dec_dependencies(self):
- super(PreviewCommunity, self).dec_dependencies()
-
- if self._dependencies <= 0:
- # unload after the grace period
- self._dispersy.callback.replace_register(self._auto_unload_identifier, self.auto_unload_community, delay=300.0)
-
- def auto_unload_community(self):
- if self._dependencies <=0:
- if __debug__: dprint("cleanup", box=1)
- self.unload_community()
-
- def on_text(self, messages, mark_as_hot=False):
- return super(PreviewCommunity, self).on_text(messages, mark_as_hot=mark_as_hot)
-
- def start_candidate_walker(self):
- assert not self._enable_walker
- self._enable_walker = True
- # hacking the walker...
- self._dispersy._walker_commmunities.insert(0, self)
- # restart walker scheduler
- self._dispersy.callback.replace_register(CANDIDATE_WALKER_CALLBACK_ID, self._dispersy._candidate_walker)
-
- def join_square(self):
- return self._dispersy.reclassify_community(self, SquareCommunity)
-
- @property
- def dispersy_acceptable_global_time_range(self):
- if self._enable_walker:
- return super(PreviewCommunity, self).dispersy_acceptable_global_time_range
- else:
- # we will accept the full 64 bit global time range
- return 2**64-1
-
- @property
- def dispersy_enable_candidate_walker(self):
- return self._enable_walker
-
- @property
- def dispersy_enable_candidate_walker_responses(self):
- # allow responses, otherwise we will not be able to enable/disable the walker on demand
- return True
-
-
-from events import getEventBroker
View
130 src/square/conversion.py
@@ -1,130 +0,0 @@
-from struct import pack, unpack_from
-
-from dispersy.conversion import BinaryConversion
-from dispersy.message import DropPacket, DelayPacketByMissingLastMessage
-
-class Conversion(BinaryConversion):
- def __init__(self, community):
- super(Conversion, self).__init__(community, "\x01")
- self.define_meta_message(chr(2), community.get_meta_message(u"member-info"), self._encode_member_info, self._decode_member_info)
- self.define_meta_message(chr(3), community.get_meta_message(u"square-info"), self._encode_square_info, self._decode_square_info)
- self.define_meta_message(chr(5), community.get_meta_message(u"text"), self._encode_text, self._decode_text)
-
- def _encode_member_info(self, message):
- alias = message.payload.alias.encode("UTF-8")
- thumbnail_hash = message.payload.thumbnail_hash or "\x00" * 20
- return pack("!B", min(len(alias), 256-1)), alias[:256-1], thumbnail_hash
-
- def _decode_member_info(self, placeholder, offset, data):
- if len(data) < offset + 1:
- raise DropPacket("Insufficient packet size")
- alias_length, = unpack_from("!B", data, offset)
- offset += 1
-
- if len(data) < offset + alias_length:
- raise DropPacket("Insufficient packet size")
- try:
- alias = data[offset:offset+alias_length].decode("UTF-8")
- except UnicodeError:
- raise DropPacket("Unable to decode UTF-8")
- offset += alias_length
-
- if len(data) < offset + 20:
- raise DropPacket("Insufficient packet size")
- thumbnail_hash = data[offset:offset+20]
- if thumbnail_hash == "\x00" * 20:
- thumbnail_hash = ""
- offset += 20
-
- return offset, placeholder.meta.payload.implement(alias, thumbnail_hash)
-
- def _encode_square_info(self, message):
- title = message.payload.title.encode("UTF-8")
- description = message.payload.description.encode("UTF-8")
- thumbnail_hash = message.payload.thumbnail_hash or "\x00" * 20
- location = message.payload.location
- radius = message.payload.radius
- return (pack("!B", min(len(title), 256-1)), title[:256-1],
- pack("!H", min(len(description), 1024-1)), description[:1024-1],
- thumbnail_hash,
- pack("!LLL", location[0], location[1], radius))
-
- def _decode_square_info(self, placeholder, offset, data):
- if len(data) < offset + 1:
- raise DropPacket("Insufficient packet size")
- title_length, = unpack_from("!B", data, offset)
- offset += 1
-
- if len(data) < offset + title_length:
- raise DropPacket("Insufficient packet size")
- try:
- title = data[offset:offset+title_length].decode("UTF-8")
- except UnicodeError:
- raise DropPacket("Unable to decode UTF-8")
- offset += title_length
-
- if len(data) < offset + 2:
- raise DropPacket("Insufficient packet size")
- description_length, = unpack_from("!H", data, offset)
- if not description_length < 1024:
- raise DropPacket("invalid description_length")
- offset += 2
-
- if len(data) < offset + description_length:
- raise DropPacket("Insufficient packet size")
- try:
- description = data[offset:offset+description_length].decode("UTF-8")
- except UnicodeError:
- raise DropPacket("Unable to decode UTF-8")
- offset += description_length
-
- if len(data) < offset + 20:
- raise DropPacket("Insufficient packet size")
- thumbnail_hash = data[offset:offset+20]
- if thumbnail_hash == "\x00" * 20:
- thumbnail_hash = ""
- offset += 20
-
- if len(data) < offset + 12:
- raise DropPacket("Insufficient packet size")
- longitude, latitude, radius, = unpack_from("!LLL", data, offset)
- offset += 12
-
- return offset, placeholder.meta.payload.implement(title, description, thumbnail_hash, (longitude, latitude), radius)
-
- def _encode_text(self, message):
- member_info_global_time = message.payload.member_info.distribution.global_time
- utc_timestamp = message.payload.utc_timestamp
- text = message.payload.text.encode("UTF-8")
- media_hash = message.payload.media_hash or "\x00" * 20
- return pack("!QqH", member_info_global_time, utc_timestamp, min(len(text), 1024-1)), text[:1024-1], media_hash
-
- def _decode_text(self, placeholder, offset, data):
- if len(data) < offset + 18:
- raise DropPacket("Insufficient packet size")
- member_info_global_time, utc_timestamp, text_length = unpack_from("!QqH", data, offset)
- member_info = self._community.dispersy.get_last_message(self._community, placeholder.authentication.member, self._community.get_meta_message(u"member-info"))
- if not (member_info and member_info_global_time <= member_info.distribution.global_time):
- raise DelayPacketByMissingLastMessage(self._community, placeholder.authentication.member, self._community.get_meta_message(u"member-info"), 1)
- utc_timestamp = long(utc_timestamp)
- if not text_length < 1024:
- raise DropPacket("invalid text_length")
- offset += 18
-
- if len(data) < offset + text_length:
- raise DropPacket("Insufficient packet size")
- try:
- text = data[offset:offset+text_length].decode("UTF-8")
- except UnicodeError:
- raise DropPacket("Unable to decode UTF-8")
- offset += text_length
-
- if len(data) < offset + 20:
- raise DropPacket("Insufficient packet size")
- media_hash = data[offset:offset+20]
- if media_hash == "\x00" * 20:
- media_hash = ""
- offset += 20
-
- return offset, placeholder.meta.payload.implement(member_info, text, media_hash, utc_timestamp)
-
View
69 src/square/database.py
@@ -1,69 +0,0 @@
-from os import path
-
-from dispersy.database import Database
-
-LATEST_VERSION = 1
-
-schema = u"""
-CREATE TABLE square(
- sync_id INTEGER, -- sync.id for square_info message
- square_id INTEGER, -- community.id for the square
- global_time INTEGER, -- sync.global_time for text message
- thumbnail_hash BLOB,
- PRIMARY KEY (sync_id));
-
-CREATE TABLE member(
- sync_id INTEGER, -- sync.id for member_info message
- member_id INTEGER, -- sync.member for member_info message
- square_id INTEGER REFERENCES square(sync_id), -- community.id for the square
- thumbnail_hash BLOB,
- PRIMARY KEY (sync_id),
- UNIQUE (member_id, square_id));
-
-CREATE TABLE text(
- sync_id INTEGER, -- sync.id for text message
- square_id INTEGER REFERENCES square(sync_id), -- community.id for the square
- member_id INTEGER REFERENCES member(sync_id), -- sync.member for member info message
- global_time INTEGER, -- sync.global_time for text message
- media_hash BLOB,
- utc_timestamp INTEGER,
- PRIMARY KEY (sync_id));
-
-CREATE VIRTUAL TABLE square_fts USING fts4(title, description, tokenize=porter);
-CREATE VIRTUAL TABLE member_fts USING fts4(alias, tokenize=porter);
-CREATE VIRTUAL TABLE text_fts USING fts4(text, tokenize=porter);
-
-CREATE TABLE option(key TEXT PRIMARY KEY, value BLOB);
-INSERT INTO option(key, value) VALUES('database_version', '""" + str(LATEST_VERSION) + """');
-"""
-
-class SquareDatabase(Database):
- if __debug__:
- __doc__ = schema
-
- def __init__(self, working_directory):
- assert isinstance(working_directory, unicode)
- Database.__init__(self, path.join(working_directory, u"square.db"))
-
- def check_database(self, database_version):
- assert isinstance(database_version, unicode)
- assert database_version.isdigit()
- assert int(database_version) >= 0
- database_version = int(database_version)
-
- if database_version == 0:
- # setup new database with current database_version
- self.executescript(schema)
-
- else:
- # upgrade an older version
-
- # upgrade from version 1 to version 2
- if database_version < 2:
- # there is no version 2 yet...
- # if __debug__: dprint("upgrade database ", database_version, " -> ", 2)
- # self.executescript(u"""UPDATE option SET value = '2' WHERE key = 'database_version';""")
- # if __debug__: dprint("upgrade database ", database_version, " -> ", 2, " (done)")
- pass
-
- return LATEST_VERSION
View
100 src/square/payload.py
@@ -1,100 +0,0 @@
-from time import time
-from datetime import datetime
-from dispersy.payload import Payload
-
-class MemberInfoPayload(Payload):
- class Implementation(Payload.Implementation):
- def __init__(self, meta, alias, thumbnail_hash):
- assert isinstance(alias, unicode)
- assert len(alias.encode("UTF-8")) < 256
- assert isinstance(thumbnail_hash, str)
- assert thumbnail_hash == "" or len(thumbnail_hash) == 20
- super(MemberInfoPayload.Implementation, self).__init__(meta)
- self._alias = alias
- self._thumbnail_hash = thumbnail_hash
-
- @property
- def alias(self):
- return self._alias
-
- @property
- def thumbnail_hash(self):
- return self._thumbnail_hash
-
-class SquareInfoPayload(Payload):
- class Implementation(Payload.Implementation):
- def __init__(self, meta, title, description, thumbnail_hash, location, radius):
- assert isinstance(title, unicode)
- assert len(title.encode("UTF-8")) < 256
- assert isinstance(description, unicode)
- assert len(description.encode("UTF-8")) < 1024
- assert isinstance(thumbnail_hash, str)
- assert thumbnail_hash == "" or len(thumbnail_hash) == 20
- assert isinstance(location, tuple)
- assert len(location) == 2
- assert isinstance(location[0], int)
- assert isinstance(location[1], int)
- assert isinstance(radius, int)
- super(SquareInfoPayload.Implementation, self).__init__(meta)
- self._title = title
- self._description = description
- self._thumbnail_hash = thumbnail_hash
- self._location = location
- self._radius = radius
-
- @property
- def title(self):
- return self._title
-
- @property
- def description(self):
- return self._description
-
- @property
- def thumbnail_hash(self):
- return self._thumbnail_hash
-
- @property
- def location(self):
- return self._location
-
- @property
- def radius(self):
- return self._radius
-
-class TextPayload(Payload):
- class Implementation(Payload.Implementation):
- def __init__(self, meta, member_info, text, media_hash, utc_timestamp):
- if __debug__:
- from dispersy.message import Message
- assert isinstance(member_info, Message.Implementation), member_info
- assert isinstance(text, unicode), text
- assert len(text.encode("UTF-8")) < 1024, text
- assert isinstance(media_hash, str), media_hash
- assert media_hash == "" or len(media_hash) == 20, media_hash
- assert (isinstance(utc_timestamp, str) and utc_timestamp == "now") or isinstance(utc_timestamp, long)
- super(TextPayload.Implementation, self).__init__(meta)
- self._member_info = member_info
- self._text = text
- self._media_hash = media_hash
- self._utc_timestamp = long(time()) if utc_timestamp == "now" else long(utc_timestamp)
-
- @property
- def member_info(self):
- return self._member_info
-
- @property
- def text(self):
- return self._text
-
- @property
- def media_hash(self):
- return self._media_hash
-
- @property
- def utc_timestamp(self):
- return self._utc_timestamp
-
- @property
- def datetime(self):
- return datetime.fromtimestamp(self._utc_timestamp)
View
16 src/square/script.py
@@ -1,16 +0,0 @@
-"""
-Example file
-
-python Tribler/Main/dispersy.py --script template
-"""
-
-from dispersy.dprint import dprint
-from dispersy.script import ScriptBase
-
-class TestScript(ScriptBase):
- def run(self):
- self.caller(self.test)
-
- def test(self):
- dprint("testing...")
- assert True
View
19 src/square/state.py
@@ -1,19 +0,0 @@
-if __debug__:
- from dispersy import dprint
-
-class State(object):
- def __init__(self, previous_state):
- if __debug__: dprint("state ", previous_state, " -> ", self)
-
-class DummyState(State):
- def __init__(self):
- pass
-
-class UnknownState(State):
- pass
-
-class SquareState(State):
- pass
-
-class TaskGroupState(State):
- pass

0 comments on commit 3ddc693

Please sign in to comment.