def xml_unicode_to_pns (e): "XML/PNS - serialize a UNICODEd XML element as 8-bit byte strings" if e.xml_attributes: yield netstring.encode (( netstring.encode (( key.encode ('utf-8'), val.encode ('utf-8') )) for key, val in e.xml_attributes.items () )) else: yield '' yield e.xml_first.encode ('utf-8') if e.xml_children: yield netstring.encode (( netstring.encode (( child.pns_name, child.xml_name.encode ('utf-8') )) for child in e.xml_children )) else: yield '' if e.xml_follow: yield e.xml_follow.encode ('utf-8') else: yield ''
def articulate_re(text, articulate, articulators, depth=0): "Articulate text using a simple regular expression lexer" bottom = len(articulators) # move down the stack until a pattern is matched ... while True: texts = [t for t in articulators[depth].split(text) if t] depth += 1 if len(texts) > 1: break if depth == bottom: # no match found, bottom of the stack reached. return text field = set() if depth == bottom: # bottom of the stack reached, simply split name = pns_model.pns_name(netstring.encode(texts), field) else: # not yet at the bottom of the stack, recurse ... name = pns_model.pns_name( netstring.encode((articulate_re(t, articulate, articulators, depth) for t in texts)), field ) # validate the articulated name(s) as a Public Names if len(field) > 1: articulate((len(field), field, name, text)) return name
def xml_unicode_to_pns(e): "XML/PNS - serialize a UNICODEd XML element as 8-bit byte strings" if e.xml_attributes: yield netstring.encode((netstring.encode( (key.encode('utf-8'), val.encode('utf-8'))) for key, val in e.xml_attributes.items())) else: yield '' yield e.xml_first.encode('utf-8') if e.xml_children: yield netstring.encode((netstring.encode( (child.pns_name, child.xml_name.encode('utf-8'))) for child in e.xml_children)) else: yield '' if e.xml_follow: yield e.xml_follow.encode('utf-8') else: yield ''
def compact_traceback (ctb): "encode a compact traceback tuple as netstrings" return netstring.encode (( ctb[0], netstring.encode ([' | '.join (x) for x in ctb[2]]), ctb[1] )), 'traceback'
def log_statement(model): "Log valid statement to STDOUT, errors to STDERR" model, error = pns_model.pns_triple(model) if error: loginfo.log(netstring.encode(model), error) return False loginfo.log(netstring.encode(model)) return True
def log_statement (model): "Log valid statement to STDOUT, errors to STDERR" model, error = pns_model.pns_triple (model) if error: loginfo.log (netstring.encode (model), error) return False loginfo.log (netstring.encode (model)) return True
def classic_traceback (ctb=None): return netstring.encode (( netstring.encode ([ 'File "%s", line %s, in %s' % ( tb[0] or '<string>', tb[2], tb[1] ) for tb in ctb[2] ]), '%s: %s' % ctb[:2] )), 'Traceback (most recent call last):'
def resolved (request): model = list (request.dns_question) if request.dns_resources == None: model.append ('') elif len (request.dns_resources) > 1: model.append (netstring.encode ( request.dns_resources )) elif request.dns_resources: model.append (request.dns_resources[0]) else: model.append ('') model.append (request.dns_peer[0]) loginfo.log (netstring.encode (model))
def __repr__(self): "return a safe netstring representation of the deque" r = [] try: self.cv.acquire() l = len(self.deque) for item in self.deque: try: r.append('%r' % (item, )) except: r.append('item id="%x"' % id(item)) finally: self.cv.release() return netstring.encode( ('protected_deque queued="%d"' % l, netstring.encode(r)))
def pns_signal (self, resolved, model): "the default resolution handler" assert None == self.log (netstring.encode (model)) if model[4] == '_' or model[4].startswith ('.'): return False return True
def pns_command (self, model): # handle a command from a PNS/TCP session assert None == self.log ( netstring.encode (model), 'command' ) if model[1]: if model[2]: # walk subject down to contexts, let the user # agent walk the graph up and down at once to # test and weight a subject against a set of # contexts (and not implement that common walk # into the client, but rather articulate it). # contexts = set (netunicode.decode ( unicode (model[2], 'UTF-8') )) self.thread_loop_queue (( self.pns_walk_simplest, (model, contexts) )) return # walk down the contexts once, in all contexts self.thread_loop_queue (( self.pns_command_predicate, (model,) )) return # walk up the names once, for in contexts self.thread_loop_queue (( self.pns_command_object, (model,) ))
def articulate_chunk(text, articulate, articulators, CHUNK, depth=0): "Articulate in chunks, usefull for larger text articulations" bottom = len(articulators) # move down the stack until a pattern is matched ... while True: texts = [t for t in articulators[depth].split(text) if t] depth += 1 if len(texts) > 1: break if depth == bottom: # no match found, bottom of the stack reached, this # is supposed to chunk, not articulate, do not name # because it is inarticulated junk ... return "" if depth == bottom: # bottom of the stack reached, simply split do not articulate # any further, there is nothing to chunk and it is a flat # articulation ... return pns_model.pns_name(netstring.encode((t for t in texts if len(t) <= CHUNK)), set()) # not yet at the bottom of the stack, recurse for t in texts: if len(t) > CHUNK: articulate_chunk(t, articulate, articulators, CHUNK, depth) else: articulate_re(t, articulate, articulators, depth) return None
def pns_join(self, context, ip, handler): "join a context at ip and subscribe the handler to its log" if self.pns_subscribed.has_key(context): self.pns_subscribed[context].append(handler) else: self.pns_subscribed[context] = [handler] self.pns_send(netstring.encode((context, '', ip, context)))
def pns_subscribe(self, context, handler): "subscribe to a context and log its statements" if self.pns_subscribed.has_key(context): self.pns_subscribed[context].append(handler) else: self.pns_subscribed[context] = [handler] self.pns_send(netstring.encode((context, '', '', context)))
def pns_quit(self, context, handler): "quit a context, unsubscribe to its log" if self.pns_subscribed.has_key(context): self.pns_subscribed[context].remove(handler) if len(self.pns_subscribed[context]) == 0: del self.pns_subscribed[context] self.pns_send(netstring.encode(('', '', '', context)))
def pns_signal(self, resolved, model): "the default resolution handler" assert None == self.log(netstring.encode(model)) if model[4] == '_' or model[4].startswith('.'): return False return True
def pns_walk_simple(self, model, contexts, walked, routes, names): assert None == self.select_trigger_log( '<walk-simple horizon="%d" walked="%d"/>' '<![CDATA[%s]]!>' % (len(names), len(walked), netstring.encode(model)), 'debug') for name in names: if name in walked: continue walked.add(name) if name in contexts: routes.setdefault(name, set()).add(name) paths = self.pns_walk_down(name, contexts) if paths: routes.setdefault(name, set()).update(paths) if len(walked) >= self.pns_horizon: # horizon reached, walk out self.pns_walk_out(model, routes) return names = self.pns_walk_up(names, walked) if len(names) == 0: # no more index to walk, walk out self.pns_walk_out(model, routes) return names = [r[1] for r in pns_weight_names(names)] self.thread_loop_queue( (self.pns_walk_simple, (model, contexts, walked, routes, names))) # >>> do another simple step
def pns_statement(model): model, error = pns_model.pns_triple(model) if error: loginfo.log(netstring.encode(model), error) return False channel.pns_statement(tuple(model[:3]), model[3]) return True
def pns_anonymous (self, model): # anonymous question, resolve in all contexts. sp = netstring.encode (model[:2]) stored = self.pns_statements.get (sp) if stored != None: bounce = model[:5] bounce[2] = netstring.encode ([ netstring.encode (i) for i in cPickle.loads (stored).items () ]) self.select_trigger (( self.pns_peer.pns_tcp_continue, (bounce, '_') )) self.select_trigger (( self.pns_peer.pns_tcp_continue, (model, '.') ))
def xml_utf8_name (element, dom): # articulate a context's name one from its children's name(s) field = set () return pns_model.pns_name (netstring.encode (( child.pns_name for child in element.xml_children if child.pns_name )), field)
def xml_utf8_to_pns(e): "XML/PNS - articulate an UTF-8 XML element as 8-bit byte strings" if e.xml_attributes: yield netstring.encode( (netstring.encode(item) for item in e.xml_attributes.items())) else: yield '' yield e.xml_first if e.xml_children: yield netstring.encode((netstring.encode( (child.pns_name, child.xml_name)) for child in e.xml_children)) else: yield '' yield e.xml_follow or ''
def xml_to_pns_continue(self, resolved, model): # handle all XML to PNS responses, assert None == loginfo.log(netstring.encode(model)) if self.pns_resolved == resolved: pass # this is the end, at least if the PNS peer does # handle each of the statement in sequence, not # answering the last one before the others. return False
def xml_to_pns_continue (self, resolved, model): # handle all XML to PNS responses, assert None == loginfo.log (netstring.encode (model)) if self.pns_resolved == resolved: pass # this is the end, at least if the PNS peer does # handle each of the statement in sequence, not # answering the last one before the others. return False
def pns_walk_out(self, model, routes): # continue the commands, drop the statements routes = pns_weight_routes(routes) assert None == self.select_trigger_log( '<walk-out routes="%d"/>' '<![CDATA[%s]]!><![CDATA[%s]]!>' % (len(routes), netstring.encode(model), encode(netunicode.encode([r[1] for r in routes]), 'UTF-8')), '') self.select_trigger((self.pns_walk_continue, (model, routes)))
def pns_quit (self, context, handler): "quit a context, unsubscribe to its log" if self.pns_subscribed.has_key (context): self.pns_subscribed[context].remove (handler) if len (self.pns_subscribed[context]) == 0: del self.pns_subscribed[context] self.pns_send (netstring.encode (( '', '', '', context )))
def pns_join (self, context, ip, handler): "join a context at ip and subscribe the handler to its log" if self.pns_subscribed.has_key (context): self.pns_subscribed[context].append (handler) else: self.pns_subscribed[context] = [handler] self.pns_send (netstring.encode (( context, '', ip, context )))
def pns_subscribe (self, context, handler): "subscribe to a context and log its statements" if self.pns_subscribed.has_key (context): self.pns_subscribed[context].append (handler) else: self.pns_subscribed[context] = [handler] self.pns_send (netstring.encode (( context, '', '', context )))
def pns_statement (model): model, error = pns_model.pns_triple (model) if error: loginfo.log (netstring.encode (model), error) return False channel.pns_statement ( tuple (model[:3]), model[3] ) return True
def xml_utf8_root (element, dom): xml_utf8_context (element, dom) dom.pns_statement (( element.pns_name or dom.pns_name, element.xml_name, netstring.encode ( xml_utf8_to_pns (element) ), dom.pns_name ))
def __repr__ (self): "return a safe netstring representation of the deque" r = [] try: self.cv.acquire () l = len (self.deque) for item in self.deque: try: r.append ('%r' % (item,)) except: r.append ( 'item id="%x"' % id (item) ) finally: self.cv.release () return netstring.encode (( 'protected_deque queued="%d"' % l, netstring.encode (r) ))
def loginfo_netlines(self, data, info=None): "log netoutlines to STDOUT, a category handler or STDERR" assert type(data) == str if info == None: self.loginfo_stdout(netstring.netlines(data)) elif self.loginfo_categories.has_key(info): self.loginfo_categories[info](netstring.netlines(data)) else: assert type(info) == str self.loginfo_stderr( netstring.netlines(netstring.encode((info, data))))
def loginfo_netstrings(self, data, info=None): "log netstrings to STDOUT, a category handler or STDERR" assert type(data) == str if info == None: self.loginfo_stdout('%d:%s,' % (len(data), data)) elif self.loginfo_categories.has_key(info): self.loginfo_categories[info]('%d:%s,' % (len(data), data)) else: assert type(info) == str encoded = netstring.encode((info, data)) self.loginfo_stderr('%d:%s,' % (len(encoded), encoded))
def pns_signal (self, resolved, model): # dump a netstring to STDOUT loginfo.log (netstring.encode (model)) # waits for the echo to finalize and articulate the # next statement, nicely as the peer sends its echo if model[4].startswith ('.'): self.pns_articulate () return False # _, ! or ? are simply dropped unless they occur # before ., ... return True
def pns_signal(self, resolved, model): # dump a netstring to STDOUT loginfo.log(netstring.encode(model)) # waits for the echo to finalize and articulate the # next statement, nicely as the peer sends its echo if model[4].startswith('.'): self.pns_articulate() return False # _, ! or ? are simply dropped unless they occur # before ., ... return True
def pns_resolve (self, model): # store, retrieve and update, but also filter statements, # returns a tuple (persistent, stored), indicating wether # the statement is to be blocked and the object stored # previously if any. # sp = netstring.encode (model[:2]) stored = self.pns_statements.get (sp) if stored == None: # new (subject, predicate): log, store and pass assert None == self.select_trigger_log ( netstring.encode (model), 'new' ) self.pns_log (model) self.pns_statements [sp] = cPickle.dumps ( {model[3]: model[2]} ) return True, None # load the {(object, context)} hash from the store persistents = cPickle.loads (stored) o = persistents.get (model[3]) if o == model[2]: # redundant contextual statement: block assert None == self.select_trigger_log ( netstring.encode (model), 'block' ) return False, None if model[2] != '': # dissent: log, update answer and pass assert None == self.select_trigger_log ( netstring.encode (model), 'update' ) self.pns_log (model) persistents[model[3]] = model[2] self.pns_statements[sp] = cPickle.dumps (persistents) return True, o
def pns_resolve (self, model, context, handler, handlers): "resolve a command or statement" handlers.append (handler or self.pns_signal) if len (handlers) == 1: # send the statement if it is not redundant encoded = netstring.encode (model) if context: encoded += '%d:%s,' % (len (context), context) else: encoded += '0:,' self.pns_send (encoded) return True return False
def http_continue (self, http): uri = http.request[1] try: uri = list (HTTP_URI.match (uri).groups ()) except: uri = ['http://', http.collector_headers.get ( 'host', self.presto_path ), uri, '', ''] else: uri[0] = uri[0] or 'http://' uri[1] = uri[1] or http.collector_headers.get ( 'host', self.presto_path ) http.uri = uri about = uri[2].split ('/', 2) about[0] = uri[1] about = http.uri_about = tuple (( unicode (urldecode (n), 'UTF-8') for n in about )) try: # context, subject and maybe predicate # || http://host/folder || http://host/folder/file controller = self.presto_cached[about] except: if len (about) > 2: about = (about[0], about[1]) else: about = (about[0],) try: # context and subject || http://host/folder controller = self.presto_cached[about] except: controller = http_404_close try: stalled = controller (http, about) except: self.loginfo_traceback () http (500) stalled = False try: digest = http.irtd2[4] except: digest = '%x' % id (http) loginfo.log (str (netstring.encode (( ' '.join (http.request), ''.join (uri[:3]), digest ))), '%d' % http.response) return stalled
def loginfo_netlines (self, data, info=None): "log netoutlines to STDOUT, a category handler or STDERR" assert type (data) == str if info == None: self.loginfo_stdout (netstring.netlines (data)) elif self.loginfo_categories.has_key (info): self.loginfo_categories[info] ( netstring.netlines (data) ) else: assert type (info) == str self.loginfo_stderr (netstring.netlines ( netstring.encode ((info, data)) ))
def pns_resolve(self, model, context, handler, handlers): "resolve a command or statement" handlers.append(handler or self.pns_signal) if len(handlers) == 1: # send the statement if it is not redundant encoded = netstring.encode(model) if context: encoded += '%d:%s,' % (len(context), context) else: encoded += '0:,' self.pns_send(encoded) return True return False
def http_continue(self, http): uri = http.request[1] try: uri = list(HTTP_URI.match(uri).groups()) except: uri = [ 'http://', http.collector_headers.get('host', self.presto_path), uri, '', '' ] else: uri[0] = uri[0] or 'http://' uri[1] = uri[1] or http.collector_headers.get( 'host', self.presto_path) http.uri = uri about = uri[2].split('/', 2) about[0] = uri[1] about = http.uri_about = tuple( (unicode(urldecode(n), 'UTF-8') for n in about)) try: # context, subject and maybe predicate # || http://host/folder || http://host/folder/file controller = self.presto_cached[about] except: if len(about) > 2: about = (about[0], about[1]) else: about = (about[0], ) try: # context and subject || http://host/folder controller = self.presto_cached[about] except: controller = http_404_close try: stalled = controller(http, about) except: self.loginfo_traceback() http(500) stalled = False try: digest = http.irtd2[4] except: digest = '%x' % id(http) loginfo.log( str( netstring.encode( (' '.join(http.request), ''.join(uri[:3]), digest))), '%d' % http.response) return stalled
def loginfo_netstrings (self, data, info=None): "log netstrings to STDOUT, a category handler or STDERR" assert type (data) == str if info == None: self.loginfo_stdout ('%d:%s,' % (len (data), data)) elif self.loginfo_categories.has_key (info): self.loginfo_categories[info] ( '%d:%s,' % (len (data), data) ) else: assert type (info) == str encoded = netstring.encode ((info, data)) self.loginfo_stderr ( '%d:%s,' % (len (encoded), encoded) )
def xml_utf8_to_pns (e): "XML/PNS - articulate an UTF-8 XML element as 8-bit byte strings" if e.xml_attributes: yield netstring.encode (( netstring.encode (item) for item in e.xml_attributes.items () )) else: yield '' yield e.xml_first if e.xml_children: yield netstring.encode (( netstring.encode (( child.pns_name, child.xml_name )) for child in e.xml_children )) else: yield '' yield e.xml_follow or ''
def xml_unicode_to_pns(self, element, context): try: pns = element.xml_attributes.pop(u'pns') except: element.pns_name = '' subject = context else: element.pns_name = subject = pns.encode('utf-8') if element.xml_children: for child in element.xml_children: self.xml_unicode_to_pns(child, subject) self.pns_statement((subject, element.xml_name.encode('utf-8'), netstring.encode(xml_unicode_to_pns(element))), context, self.xml_to_pns_continue) if subject != context: element.xml_attributes[u'pns'] = pns
def pns_walk_out (self, model, routes): # continue the commands, drop the statements routes = pns_weight_routes (routes) assert None == self.select_trigger_log ( '<walk-out routes="%d"/>' '<![CDATA[%s]]!><![CDATA[%s]]!>' % ( len (routes), netstring.encode (model), encode (netunicode.encode ( [r[1] for r in routes] ), 'UTF-8') ), '' ) self.select_trigger (( self.pns_walk_continue, (model, routes) ))
def xml_utf8_to_pns (self, element, context): try: element.pns_name = subject = \ element.xml_attributes.pop ('pns') except: element.pns_name = '' subject = context if element.xml_children: for child in element.xml_children: self.xml_utf8_to_pns (child, subject) self.pns_statement (( subject, element.xml_name, netstring.encode (xml_utf8_to_pns (element)), ), context, self.xml_to_pns_continue) if subject != context: element.xml_attributes['pns'] = subject
def xml_utf8_to_pns(self, element, context): try: element.pns_name = subject = \ element.xml_attributes.pop ('pns') except: element.pns_name = '' subject = context if element.xml_children: for child in element.xml_children: self.xml_utf8_to_pns(child, subject) self.pns_statement(( subject, element.xml_name, netstring.encode(xml_utf8_to_pns(element)), ), context, self.xml_to_pns_continue) if subject != context: element.xml_attributes['pns'] = subject
def xml_unicode_to_pns (self, element, context): try: pns = element.xml_attributes.pop (u'pns') except: element.pns_name = '' subject = context else: element.pns_name = subject = pns.encode ('utf-8') if element.xml_children: for child in element.xml_children: self.xml_unicode_to_pns (child, subject) self.pns_statement (( subject, element.xml_name.encode ('utf-8'), netstring.encode (xml_unicode_to_pns (element)) ), context, self.xml_to_pns_continue) if subject != context: element.xml_attributes[u'pns'] = pns
def xml_utf8_context(element, dom): if not element.xml_children: return context = element.pns_name or dom.pns_name for child in element.xml_children: # A PNS/XML statement with the same context and subject is a # leaf. All other are branches, that have their parent's name # has contexts but not as subject. # dom.pns_statement((child.pns_name or context, child.xml_name, netstring.encode(xml_utf8_to_pns(child)), context)) child.xml_children = None # drop articulated children now! # articulate the child SATs in this element's context for articulated in child.pns_sat_articulated: if not dom.pns_statement( (articulated[2], 'sat', articulated[3], context)): break
def run (self): """The Thread Loop If thread_loop_init() is True call queued instance until None is popped or and exception is raised and not catched by thread_loop_throw. Finally, if thread_loop_delete() is True, trunk the thread loop queue. """ if self.thread_loop_init (): next = self.thread_loop_queue.popleft # ? maybe safer while True: queued = next () # ... sure faster if queued == None: break try: queued[0] (*queued[1]) except: if self.thread_loop_throw (): del queued break else: del queued # # note that I make sure to delete the tuple which # would otherwise hold a reference to the method and # arguments of the call threaded, preventing garbage # collection hence finalization and was the source # of subtle bugs ... # if self.thread_loop_delete (): trunked = self.thread_loop_queue.trunk () if trunked: assert None == self.select_trigger_log ( netstring.encode ([ '%r' % (i,) for i in trunked ]), 'debug' )
def pns_command(self, model): # handle a command from a PNS/TCP session assert None == self.log(netstring.encode(model), 'command') if model[1]: if model[2]: # walk subject down to contexts, let the user # agent walk the graph up and down at once to # test and weight a subject against a set of # contexts (and not implement that common walk # into the client, but rather articulate it). # contexts = set(netunicode.decode(unicode(model[2], 'UTF-8'))) self.thread_loop_queue( (self.pns_walk_simplest, (model, contexts))) return # walk down the contexts once, in all contexts self.thread_loop_queue((self.pns_command_predicate, (model, ))) return # walk up the names once, for in contexts self.thread_loop_queue((self.pns_command_object, (model, )))
def xml_utf8_context (element, dom): if not element.xml_children: return context = element.pns_name or dom.pns_name for child in element.xml_children: # A PNS/XML statement with the same context and subject is a # leaf. All other are branches, that have their parent's name # has contexts but not as subject. # dom.pns_statement (( child.pns_name or context, child.xml_name, netstring.encode (xml_utf8_to_pns (child)), context )) child.xml_children = None # drop articulated children now! # articulate the child SATs in this element's context for articulated in child.pns_sat_articulated: if not dom.pns_statement (( articulated[2], 'sat', articulated[3], context )): break
def pns_name(encoded, horizon, HORIZON=126): # Recursively validate a Public Name, returns the empty string if # the name encoded is invalid or inside the horizon. This function # does more than just assert that the encoded 8-bit byte string is # a valid public name: it transform it to a valid public name. # # try to decode the articulated public names names = [n for n in netstring.decode(encoded) if n] if not names: if encoded not in horizon and pns_name_clean(encoded): # clean name new in this horizon horizon.add(encoded) return encoded # unsafe 8-bit byte string or Public Name in the in horizon return '' # articulated Public Names valid = [] for name in names: # recursively validate each articulated name in this horizon name = pns_name(name, horizon, HORIZON) if name: valid.append(name) if len(horizon) >= HORIZON: break # but only under this HORIZON if len(valid) > 1: # sort Public Names and encode valid.sort() return netstring.encode(valid) if len(valid) > 0: # return a "singleton" return valid[0] return '' # nothing valid to articulate in this horizon
def pns_name (encoded, horizon, HORIZON=126): # Recursively validate a Public Name, returns the empty string if # the name encoded is invalid or inside the horizon. This function # does more than just assert that the encoded 8-bit byte string is # a valid public name: it transform it to a valid public name. # # try to decode the articulated public names names = [n for n in netstring.decode (encoded) if n] if not names: if encoded not in horizon and pns_name_clean (encoded): # clean name new in this horizon horizon.add (encoded) return encoded # unsafe 8-bit byte string or Public Name in the in horizon return '' # articulated Public Names valid = [] for name in names: # recursively validate each articulated name in this horizon name = pns_name (name, horizon, HORIZON) if name: valid.append (name) if len (horizon) >= HORIZON: break # but only under this HORIZON if len (valid) > 1: # sort Public Names and encode valid.sort () return netstring.encode (valid) if len (valid) > 0: # return a "singleton" return valid[0] return '' # nothing valid to articulate in this horizon
def run(self): """The Thread Loop If thread_loop_init() is True call queued instance until None is popped or and exception is raised and not catched by thread_loop_throw. Finally, if thread_loop_delete() is True, trunk the thread loop queue. """ if self.thread_loop_init(): next = self.thread_loop_queue.popleft # ? maybe safer while True: queued = next() # ... sure faster if queued == None: break try: queued[0](*queued[1]) except: if self.thread_loop_throw(): del queued break else: del queued # # note that I make sure to delete the tuple which # would otherwise hold a reference to the method and # arguments of the call threaded, preventing garbage # collection hence finalization and was the source # of subtle bugs ... # if self.thread_loop_delete(): trunked = self.thread_loop_queue.trunk() if trunked: assert None == self.select_trigger_log( netstring.encode(['%r' % (i, ) for i in trunked]), 'debug')
def pns_statement (self, model): # handle PNS/TCP statements either directly from persistence # or not-relayed original statements sp = netstring.encode (model[:2]) o = self.pns_buffer.get (sp) if o != None: # buffered statement, TODO: drop or buffer? model[2] = o return # not buffered, echo to all subscribers, set timeout and buffer self.pns_tcp_continue (model[:4], '.') self.pns_peer.pns_udp.timeouts_push ( (self.pns_right or self.pns_name, sp) ) self.pns_buffer[sp] = model[2] if self.pns_left and self.pns_right: # joined: record as stated, index and relay self.pns_peer.pns_inference.pns_map (model) self.pns_statements[sp] = model[2] if model[2]: # answer right self.pns_sendto_right ('%s%d:%s,' % ( sp, len (model[2]), model[2] ), self.pns_right) return # question left self.sendto (sp, (self.pns_left, 3534)) return # not relayed if model[3] == self.pns_name: # route named statements that cannot be relayed self.pns_peer.pns_inference.pns_statement (model[:4]) return
def classic_traceback(ctb=None): return netstring.encode((netstring.encode([ 'File "%s", line %s, in %s' % (tb[0] or '<string>', tb[2], tb[1]) for tb in ctb[2] ]), '%s: %s' % ctb[:2])), 'Traceback (most recent call last):'
def compact_traceback(ctb): "encode a compact traceback tuple as netstrings" return netstring.encode( (ctb[0], netstring.encode([' | '.join(x) for x in ctb[2]]), ctb[1])), 'traceback'
def loginfo_log(self, data, info=None): """log a message with this instance's __repr__ and an optional category""" self.loginfo_logger.log(netstring.encode(('%r' % self, '%s' % data)), info)