]> jfr.im git - irc/weechat/qweechat.git/blobdiff - src/qweechat/weechat/protocol.py
Update copyright dates
[irc/weechat/qweechat.git] / src / qweechat / weechat / protocol.py
index 40f1a4aa5396540baa7c4f08d5cbfce67daea9f2..02b06367b66d9c130b2b43df75dab581b6e254ea 100644 (file)
@@ -1,7 +1,9 @@
 #!/usr/bin/python
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2011-2012 Sebastien Helleu <flashcode@flashtux.org>
+# protocol.py - decode binary messages received from WeeChat/relay
+#
+# Copyright (C) 2011-2014 Sébastien Helleu <flashcode@flashtux.org>
 #
 # This file is part of QWeeChat, a Qt remote GUI for WeeChat.
 #
 #
 
 #
-# Decode binary messages received from WeeChat/relay.
-#
-# For info about protocol and format of messages, please read document "WeeChat Relay Protocol",
-# available at:  http://www.weechat.org/doc/
+# For info about protocol and format of messages, please read document
+# "WeeChat Relay Protocol", available at:  http://weechat.org/doc/
 #
 # History:
 #
-# 2011-11-23, Sebastien Helleu <flashcode@flashtux.org>:
+# 2011-11-23, Sébastien Helleu <flashcode@flashtux.org>:
 #     start dev
 #
 
-import struct, zlib
+import collections, struct, zlib
+
+if hasattr(collections, 'OrderedDict'):
+    # python >= 2.7
+    class WeechatDict(collections.OrderedDict):
+        def __str__(self):
+            return '{%s}' % ', '.join(['%s: %s' % (repr(key), repr(self[key])) for key in self])
+else:
+    # python <= 2.6
+    WeechatDict = dict
 
 class WeechatObject:
-    def __init__(self, objtype, value):
+    def __init__(self, objtype, value, separator='\n'):
         self.objtype = objtype;
         self.value = value
+        self.separator = separator
+        self.indent = '  ' if separator == '\n' else ''
+        self.separator1 = '\n%s' % self.indent if separator == '\n' else ''
 
     def _str_value(self, v):
         if type(v) is str and not v is None:
@@ -44,19 +56,17 @@ class WeechatObject:
         return str(v)
 
     def _str_value_hdata(self):
-        lines = ['',
-                 '  keys: %s' % str(self.value['keys']),
-                 '  path: %s' % str(self.value['path'])]
+        lines = ['%skeys: %s%s%spath: %s' % (self.separator1, str(self.value['keys']), self.separator, self.indent, str(self.value['path']))]
         for i, item in enumerate(self.value['items']):
-            lines.append('  item %d:' % (i + 1))
-            lines.append('\n'.join(['    %s: %s' % (key, self._str_value(value)) for key, value in sorted(item.items())]))
+            lines.append('  item %d:%s%s' % ((i + 1), self.separator,
+                                             self.separator.join(['%s%s: %s' % (self.indent * 2, key, self._str_value(value)) for key, value in item.items()])))
         return '\n'.join(lines)
 
     def _str_value_infolist(self):
-        lines = ['', '  name: %s' % self.value['name']]
+        lines = ['%sname: %s' % (self.separator1, self.value['name'])]
         for i, item in enumerate(self.value['items']):
-            lines.append('  item %d:' % (i + 1))
-            lines.append('\n'.join(['    %s: %s' % (key, self._str_value(value)) for key, value in sorted(item.items())]))
+            lines.append('  item %d:%s%s' % ((i + 1), self.separator,
+                                             self.separator.join(['%s%s: %s' % (self.indent * 2, key, self._str_value(value)) for key, value in item.items()])))
         return '\n'.join(lines)
 
     def _str_value_other(self):
@@ -70,8 +80,11 @@ class WeechatObject:
 
 
 class WeechatObjects(list):
+    def __init__(self, separator='\n'):
+        self.separator = separator
+
     def __str__(self):
-        return '\n'.join([str(obj) for obj in self])
+        return self.separator.join([str(obj) for obj in self])
 
 
 class WeechatMessage:
@@ -193,7 +206,7 @@ class Protocol:
         type_keys = self._obj_type()
         type_values = self._obj_type()
         count = self._obj_int()
-        hashtable = {}
+        hashtable = WeechatDict()
         for i in range(0, count):
             key = self._obj_cb[type_keys]()
             value = self._obj_cb[type_values]()
@@ -208,14 +221,15 @@ class Protocol:
         list_path = path.split('/')
         list_keys = keys.split(',')
         keys_types = []
-        dict_keys = {}
+        dict_keys = WeechatDict()
         for key in list_keys:
             items = key.split(':')
             keys_types.append(items)
             dict_keys[items[0]] = items[1]
         items = []
         for i in range(0, count):
-            item = {}
+            item = WeechatDict()
+            item['__path'] = []
             pointers = []
             for p in range(0, len(list_path)):
                 pointers.append(self._obj_ptr())
@@ -242,7 +256,7 @@ class Protocol:
         items = []
         for i in range(0, count_items):
             count_vars = self._obj_int()
-            variables = {}
+            variables = WeechatDict()
             for v in range(0, count_vars):
                 var_name = self._obj_str()
                 var_type = self._obj_type()
@@ -260,7 +274,7 @@ class Protocol:
             values.append(self._obj_cb[type_values]())
         return values
 
-    def decode(self, data):
+    def decode(self, data, separator='\n'):
         """Decode binary data and return list of objects."""
         self.data = data
         size = len(self.data)
@@ -273,6 +287,8 @@ class Protocol:
             size_uncompressed = len(uncompressed) + 5
             uncompressed = '%s%s%s' % (struct.pack('>i', size_uncompressed), struct.pack('b', 0), uncompressed)
             self.data = uncompressed
+        else:
+            uncompressed = self.data[:]
         # skip length and compression flag
         self.data = self.data[5:]
         # read id
@@ -280,11 +296,11 @@ class Protocol:
         if msgid is None:
             msgid = ''
         # read objects
-        objects = WeechatObjects()
+        objects = WeechatObjects(separator=separator)
         while len(self.data) > 0:
             objtype = self._obj_type()
             value = self._obj_cb[objtype]()
-            objects.append(WeechatObject(objtype, value))
+            objects.append(WeechatObject(objtype, value, separator=separator))
         return WeechatMessage(size, size_uncompressed, compression, uncompressed, msgid, objects)