Passed
Pull Request — master (#291)
by Marek
02:19
created

ige.IMarshal.IMarshal.__init__()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 1
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
#
2
#  Copyright 2001 - 2016 Ludek Smid [http://www.ospace.net/]
3
#
4
#  This file is part of Outer Space.
5
#
6
#  Outer Space is free software; you can redistribute it and/or modify
7
#  it under the terms of the GNU General Public License as published by
8
#  the Free Software Foundation; either version 2 of the License, or
9
#  (at your option) any later version.
10
#
11
#  Outer Space is distributed in the hope that it will be useful,
12
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
#  GNU General Public License for more details.
15
#
16
#  You should have received a copy of the GNU General Public License
17
#  along with Outer Space; if not, write to the Free Software
18
#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
#
20
import types
21
22
from IDataHolder import IDataHolder
23
import zlib, string
24
25
__all__ = ('EncodeException', 'DecodeException', 'IPacket', 'IMarshal')
26
27
class EncodeException(Exception):
28
    pass
29
30
class DecodeException(Exception):
31
    pass
32
33
class IPacket:
34
35
    def __init__(self):
36
        self.sid = None
37
        self.method = None
38
        self.params = None
39
        self.result = None
40
        self.messages = None
41
        self.exception = None
42
        self.clientAddr = None
43
44
    def __repr__(self):
45
        result = '<%s.%s %d ' % (self.__class__.__module__, self.__class__.__name__, id(self))
46
        for key, value in self.__dict__.items():
47
            result += '%s=%s, ' % (key, repr(value))
48
        result += '>'
49
        return result
50
51
class IMarshal:
52
53
    def __init__(self):
54
        pass
55
56
    def encode(self, data, version = "V20"):
57
        if version == "V20":
58
            return "V20%s" % zlib.compress(pickle.dumps(data, 1))
59
        else:
60
            raise EncodeException("Cannot handle version %s." % version)
61
62
    def decode(self, str):
63
        prefix = str[:3]
64
        if prefix == u'V20':
65
            data = pickle.loads(zlib.decompress(str[3:]))
66
        else:
67
            raise DecodeException('Cannot handle version %s [message: %s]' % (prefix, str))
68
        return data
69
70
# (de)compress dictionary
71
#try:
72
#    from ICompressScheme import compress
73
#except ImportError:
74
compress = {}
75
76
decompress = {}
77
78
for key, value in compress.items():
79
    decompress[str(value)] = key
80
81
# statistics
82
import cPickle as pickle
83
84
class Stats:
85
    def __init__(self):
86
        self.data = {}
87
        self.total = 0
88
        self.hits = 0
89
        self.totalBytes = 0
90
        self.savedBytes = 0
91
        self.encBytes = 0
92
        self.zipBytes = 0
93
94
# load stats TODO remove profiling code
95
# TODO change dir according to config file
96
try:
97
    fh = open('var/marshal.stats.data', 'rb')
98
    stats = pickle.load(fh)
99
    fh.close()
100
except IOError, e:
101
    stats = Stats()
102
except EOFError, e:
103
    stats = Stats()
104
105
def saveStats(directory):
106
    print 'Saving IMarshal statistics'
107
    # stats
108
    fh = open(os.path.join(directory, 'marshal.stats.data'), 'wb')
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable os does not seem to be defined.
Loading history...
109
    pickle.dump(stats, fh, 1)
110
    fh.close()
111
    # various data
112
    keys = []
113
    for key in stats.data.keys():
114
        keys.append((len(key) * stats.data[key],key))
115
    keys.sort()
116
    keys.reverse()
117
    fstats = open(os.path.join(directory, 'marshal.stats'), 'w')
118
    fscheme = open(os.path.join(directory, 'marshal.cscheme'), 'w')
119
    fpysrc = open(os.path.join(directory, 'marshal.cscheme.py'), 'w')
120
    print >> fpysrc, 'compress = {'
121
    print >> fstats, '# Summary'
122
    print >> fstats, '# Total strings:', stats.total
123
    print >> fstats, '# Compressed strings:', stats.hits
124
    print >> fstats, '# Uncompressed strings:', stats.total - stats.hits
125
    print >> fstats, '# Ratio:', stats.hits / stats.total * 100L, '%'
126
    print >> fstats, '# Uncompressed size:', stats.totalBytes
127
    print >> fstats, '# Compressed size:', stats.totalBytes - stats.savedBytes
128
    print >> fstats, '# Saved bytes:', stats.savedBytes
129
    print >> fstats, '# Ratio:', stats.savedBytes / stats.totalBytes * 100L, '%'
130
    print >> fstats, '# Encoded pckt bytes total:', stats.encBytes
131
    print >> fstats, '# Encoded pckt bytes total (no compression, est.):', stats.encBytes + stats.savedBytes
132
    print >> fstats, '# Ratio:', stats.encBytes / (stats.encBytes + stats.savedBytes) * 100L, '%'
133
    print >> fstats, '# Encoded pckt bytes total (zipped):', stats.zipBytes
134
    print >> fstats, '# Ratio (to compressed):', stats.zipBytes / stats.encBytes * 100L, '%'
135
    print >> fstats, '# Ratio (to uncompressed):', stats.zipBytes / (stats.encBytes + stats.savedBytes)* 100L , '%'
136
    print >> fstats, '# total bytes,number of items,string'
137
    index = 0
138
    for key in keys:
139
        count, name = key
140
        print >> fstats, '%d,%d,%s' % (count, stats.data[name], name)
141
        code = makeCode(index)
142
        # include in scheme when there is save in bytes
143
        if len(code) < len(name):
144
            print >> fscheme, code, name
145
            print >> fpysrc, "    '%s' : '%s'," % (name, code)
146
        index += 1
147
    print >>fpysrc, '}'
148
    fstats.close()
149
    fscheme.close()
150
    fpysrc.close()
151
152
codeChars = '0123456789abcdefghjiklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
153
154
def makeCode(index):
155
    if index < len(codeChars):
156
        return codeChars[index]
157
    elif index / len(codeChars) - 1 < len(codeChars):
158
        return '%s%s' % (
159
            codeChars[index / len(codeChars) - 1],
160
            codeChars[index % len(codeChars)]
161
        )
162
    else:
163
        return None
164
165
# testing only
166
if __name__ == '__main__':
167
168
    packet = IPacket()
169
    packet.sid = '0123456789'
170
    packet.method = 'test'
171
    packet.params = { 'name':u'Corvus', 'componentOf':1001, 'rules':[1,2], 'isA': (1,2) }
172
    marshal = IMarshal()
173
174
    str = marshal.encode(packet)
175
176
    print repr(str)
177
    print len(str)
178
    packet = marshal.decode(str)
179
    print packet.params
180
181
    import pprint
182
    pprint.pprint(packet.params)
183
184