rencode 1.0.9__cp313-cp313-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
rencode/__init__.py ADDED
@@ -0,0 +1,12 @@
1
+ try:
2
+ from rencode._rencode import *
3
+ from rencode._rencode import __version__
4
+ except ImportError:
5
+ import rencode.rencode_orig
6
+ prev_all = rencode.rencode_orig.__all__[:]
7
+ del rencode.rencode_orig.__all__
8
+ from rencode.rencode_orig import *
9
+ from rencode.rencode_orig import __version__
10
+ rencode.rencode_orig.__all__ = prev_all
11
+
12
+ __all__ = ['dumps', 'loads']
Binary file
@@ -0,0 +1,514 @@
1
+ # Original bencode module by Petru Paler, et al.
2
+ #
3
+ # Modifications by Connelly Barnes:
4
+ #
5
+ # - Added support for floats (sent as 32-bit or 64-bit in network
6
+ # order), bools, None.
7
+ # - Allowed dict keys to be of any serializable type.
8
+ # - Lists/tuples are always decoded as tuples (thus, tuples can be
9
+ # used as dict keys).
10
+ # - Embedded extra information in the 'typecodes' to save some space.
11
+ # - Added a restriction on integer length, so that malicious hosts
12
+ # cannot pass us large integers which take a long time to decode.
13
+ #
14
+ # Licensed by Bram Cohen under the "MIT license":
15
+ #
16
+ # "Copyright (C) 2001-2002 Bram Cohen
17
+ #
18
+ # Permission is hereby granted, free of charge, to any person
19
+ # obtaining a copy of this software and associated documentation files
20
+ # (the "Software"), to deal in the Software without restriction,
21
+ # including without limitation the rights to use, copy, modify, merge,
22
+ # publish, distribute, sublicense, and/or sell copies of the Software,
23
+ # and to permit persons to whom the Software is furnished to do so,
24
+ # subject to the following conditions:
25
+ #
26
+ # The above copyright notice and this permission notice shall be
27
+ # included in all copies or substantial portions of the Software.
28
+ #
29
+ # The Software is provided "AS IS", without warranty of any kind,
30
+ # express or implied, including but not limited to the warranties of
31
+ # merchantability, fitness for a particular purpose and
32
+ # noninfringement. In no event shall the authors or copyright holders
33
+ # be liable for any claim, damages or other liability, whether in an
34
+ # action of contract, tort or otherwise, arising from, out of or in
35
+ # connection with the Software or the use or other dealings in the
36
+ # Software."
37
+ #
38
+ # (The rencode module is licensed under the above license as well).
39
+ #
40
+ # pylint: disable=redefined-builtin
41
+
42
+ """
43
+ rencode -- Web safe object pickling/unpickling.
44
+
45
+ Public domain, Connelly Barnes 2006-2007.
46
+
47
+ The rencode module is a modified version of bencode from the
48
+ BitTorrent project. For complex, heterogeneous data structures with
49
+ many small elements, r-encodings take up significantly less space than
50
+ b-encodings:
51
+
52
+ >>> len(rencode.dumps({'a':0, 'b':[1,2], 'c':99}))
53
+ 13
54
+ >>> len(bencode.bencode({'a':0, 'b':[1,2], 'c':99}))
55
+ 26
56
+
57
+ The rencode format is not standardized, and may change with different
58
+ rencode module versions, so you should check that you are using the
59
+ same rencode version throughout your project.
60
+ """
61
+
62
+ import struct
63
+ import sys
64
+ from threading import Lock
65
+
66
+ __version__ = ("Python", 1, 0, 9)
67
+ __all__ = ("dumps", "loads")
68
+
69
+ py3 = sys.version_info[0] >= 3
70
+ if py3:
71
+ long = int
72
+ unicode = str
73
+
74
+ def int2byte(c):
75
+ return bytes([c])
76
+
77
+
78
+ else:
79
+
80
+ def int2byte(c):
81
+ return chr(c)
82
+
83
+
84
+ # Default number of bits for serialized floats, either 32 or 64 (also a parameter for dumps()).
85
+ DEFAULT_FLOAT_BITS = 32
86
+
87
+ # Maximum length of integer when written as base 10 string.
88
+ MAX_INT_LENGTH = 64
89
+
90
+ # The bencode 'typecodes' such as i, d, etc have been extended and
91
+ # relocated on the base-256 character set.
92
+ CHR_LIST = int2byte(59)
93
+ CHR_DICT = int2byte(60)
94
+ CHR_INT = int2byte(61)
95
+ CHR_INT1 = int2byte(62)
96
+ CHR_INT2 = int2byte(63)
97
+ CHR_INT4 = int2byte(64)
98
+ CHR_INT8 = int2byte(65)
99
+ CHR_FLOAT32 = int2byte(66)
100
+ CHR_FLOAT64 = int2byte(44)
101
+ CHR_TRUE = int2byte(67)
102
+ CHR_FALSE = int2byte(68)
103
+ CHR_NONE = int2byte(69)
104
+ CHR_TERM = int2byte(127)
105
+
106
+ # Positive integers with value embedded in typecode.
107
+ INT_POS_FIXED_START = 0
108
+ INT_POS_FIXED_COUNT = 44
109
+
110
+ # Dictionaries with length embedded in typecode.
111
+ DICT_FIXED_START = 102
112
+ DICT_FIXED_COUNT = 25
113
+
114
+ # Negative integers with value embedded in typecode.
115
+ INT_NEG_FIXED_START = 70
116
+ INT_NEG_FIXED_COUNT = 32
117
+
118
+ # Strings with length embedded in typecode.
119
+ STR_FIXED_START = 128
120
+ STR_FIXED_COUNT = 64
121
+
122
+ # Lists with length embedded in typecode.
123
+ LIST_FIXED_START = STR_FIXED_START + STR_FIXED_COUNT
124
+ LIST_FIXED_COUNT = 64
125
+
126
+ # Whether strings should be decoded when loading
127
+ _decode_utf8 = False
128
+
129
+
130
+ def decode_int(x, f):
131
+ f += 1
132
+ newf = x.index(CHR_TERM, f)
133
+ if newf - f >= MAX_INT_LENGTH:
134
+ raise ValueError("overflow")
135
+ try:
136
+ n = int(x[f:newf])
137
+ except (OverflowError, ValueError):
138
+ n = long(x[f:newf])
139
+ if x[f : f + 1] == "-":
140
+ if x[f + 1 : f + 2] == "0":
141
+ raise ValueError
142
+ elif x[f : f + 1] == "0" and newf != f + 1:
143
+ raise ValueError
144
+ return (n, newf + 1)
145
+
146
+
147
+ def decode_intb(x, f):
148
+ f += 1
149
+ return (struct.unpack("!b", x[f : f + 1])[0], f + 1)
150
+
151
+
152
+ def decode_inth(x, f):
153
+ f += 1
154
+ return (struct.unpack("!h", x[f : f + 2])[0], f + 2)
155
+
156
+
157
+ def decode_intl(x, f):
158
+ f += 1
159
+
160
+ return (struct.unpack("!l", x[f : f + 4])[0], f + 4)
161
+
162
+
163
+ def decode_intq(x, f):
164
+ f += 1
165
+ return (struct.unpack("!q", x[f : f + 8])[0], f + 8)
166
+
167
+
168
+ def decode_float32(x, f):
169
+ f += 1
170
+ n = struct.unpack("!f", x[f : f + 4])[0]
171
+ return (n, f + 4)
172
+
173
+
174
+ def decode_float64(x, f):
175
+ f += 1
176
+ n = struct.unpack("!d", x[f : f + 8])[0]
177
+ return (n, f + 8)
178
+
179
+
180
+ def decode_string(x, f):
181
+ colon = x.index(b":", f)
182
+ try:
183
+ n = int(x[f:colon])
184
+ except (OverflowError, ValueError):
185
+ n = long(x[f:colon])
186
+ if x[f] == "0" and colon != f + 1:
187
+ raise ValueError
188
+ colon += 1
189
+ s = x[colon : colon + n]
190
+ if _decode_utf8:
191
+ s = s.decode("utf8")
192
+ return (s, colon + n)
193
+
194
+
195
+ def decode_list(x, f):
196
+ r, f = [], f + 1
197
+ while x[f : f + 1] != CHR_TERM:
198
+ v, f = decode_func[x[f : f + 1]](x, f)
199
+ r.append(v)
200
+ return (tuple(r), f + 1)
201
+
202
+
203
+ def decode_dict(x, f):
204
+ r, f = {}, f + 1
205
+ while x[f : f + 1] != CHR_TERM:
206
+ k, f = decode_func[x[f : f + 1]](x, f)
207
+ r[k], f = decode_func[x[f : f + 1]](x, f)
208
+ return (r, f + 1)
209
+
210
+
211
+ def decode_true(x, f):
212
+ return (True, f + 1)
213
+
214
+
215
+ def decode_false(x, f):
216
+ return (False, f + 1)
217
+
218
+
219
+ def decode_none(x, f):
220
+ return (None, f + 1)
221
+
222
+
223
+ decode_func = {}
224
+ decode_func[b"0"] = decode_string
225
+ decode_func[b"1"] = decode_string
226
+ decode_func[b"2"] = decode_string
227
+ decode_func[b"3"] = decode_string
228
+ decode_func[b"4"] = decode_string
229
+ decode_func[b"5"] = decode_string
230
+ decode_func[b"6"] = decode_string
231
+ decode_func[b"7"] = decode_string
232
+ decode_func[b"8"] = decode_string
233
+ decode_func[b"9"] = decode_string
234
+ decode_func[CHR_LIST] = decode_list
235
+ decode_func[CHR_DICT] = decode_dict
236
+ decode_func[CHR_INT] = decode_int
237
+ decode_func[CHR_INT1] = decode_intb
238
+ decode_func[CHR_INT2] = decode_inth
239
+ decode_func[CHR_INT4] = decode_intl
240
+ decode_func[CHR_INT8] = decode_intq
241
+ decode_func[CHR_FLOAT32] = decode_float32
242
+ decode_func[CHR_FLOAT64] = decode_float64
243
+ decode_func[CHR_TRUE] = decode_true
244
+ decode_func[CHR_FALSE] = decode_false
245
+ decode_func[CHR_NONE] = decode_none
246
+
247
+
248
+ def make_fixed_length_string_decoders():
249
+ def make_decoder(slen):
250
+ def f(x, f):
251
+ s = x[f + 1 : f + 1 + slen]
252
+ if _decode_utf8:
253
+ s = s.decode("utf8")
254
+ return (s, f + 1 + slen)
255
+
256
+ return f
257
+
258
+ for i in range(STR_FIXED_COUNT):
259
+ decode_func[int2byte(STR_FIXED_START + i)] = make_decoder(i)
260
+
261
+
262
+ make_fixed_length_string_decoders()
263
+
264
+
265
+ def make_fixed_length_list_decoders():
266
+ def make_decoder(slen):
267
+ def f(x, f):
268
+ r, f = [], f + 1
269
+ for _ in range(slen):
270
+ v, f = decode_func[x[f : f + 1]](x, f)
271
+ r.append(v)
272
+ return (tuple(r), f)
273
+
274
+ return f
275
+
276
+ for i in range(LIST_FIXED_COUNT):
277
+ decode_func[int2byte(LIST_FIXED_START + i)] = make_decoder(i)
278
+
279
+
280
+ make_fixed_length_list_decoders()
281
+
282
+
283
+ def make_fixed_length_int_decoders():
284
+ def make_decoder(j):
285
+ def f(x, f):
286
+ return (j, f + 1)
287
+
288
+ return f
289
+
290
+ for i in range(INT_POS_FIXED_COUNT):
291
+ decode_func[int2byte(INT_POS_FIXED_START + i)] = make_decoder(i)
292
+ for i in range(INT_NEG_FIXED_COUNT):
293
+ decode_func[int2byte(INT_NEG_FIXED_START + i)] = make_decoder(-1 - i)
294
+
295
+
296
+ make_fixed_length_int_decoders()
297
+
298
+
299
+ def make_fixed_length_dict_decoders():
300
+ def make_decoder(slen):
301
+ def f(x, f):
302
+ r, f = {}, f + 1
303
+ for _ in range(slen):
304
+ k, f = decode_func[x[f : f + 1]](x, f)
305
+ r[k], f = decode_func[x[f : f + 1]](x, f)
306
+ return (r, f)
307
+
308
+ return f
309
+
310
+ for i in range(DICT_FIXED_COUNT):
311
+ decode_func[int2byte(DICT_FIXED_START + i)] = make_decoder(i)
312
+
313
+
314
+ make_fixed_length_dict_decoders()
315
+
316
+
317
+ def loads(x, decode_utf8=False):
318
+ global _decode_utf8
319
+ _decode_utf8 = decode_utf8
320
+ try:
321
+ r, l = decode_func[x[0:1]](x, 0)
322
+ except (IndexError, KeyError):
323
+ raise ValueError
324
+ if l != len(x):
325
+ raise ValueError
326
+ return r
327
+
328
+
329
+ def encode_int(x, r):
330
+ if 0 <= x < INT_POS_FIXED_COUNT:
331
+ r.append(int2byte(INT_POS_FIXED_START + x))
332
+ elif -INT_NEG_FIXED_COUNT <= x < 0:
333
+ r.append(int2byte(INT_NEG_FIXED_START - 1 - x))
334
+ elif -128 <= x < 128:
335
+ r.extend((CHR_INT1, struct.pack("!b", x)))
336
+ elif -32768 <= x < 32768:
337
+ r.extend((CHR_INT2, struct.pack("!h", x)))
338
+ elif -2147483648 <= x < 2147483648:
339
+ r.extend((CHR_INT4, struct.pack("!l", x)))
340
+ elif -9223372036854775808 <= x < 9223372036854775808:
341
+ r.extend((CHR_INT8, struct.pack("!q", x)))
342
+ else:
343
+ s = str(x)
344
+ if py3:
345
+ s = bytes(s, "ascii")
346
+
347
+ if len(s) >= MAX_INT_LENGTH:
348
+ raise ValueError("overflow")
349
+ r.extend((CHR_INT, s, CHR_TERM))
350
+
351
+
352
+ def encode_float32(x, r):
353
+ r.extend((CHR_FLOAT32, struct.pack("!f", x)))
354
+
355
+
356
+ def encode_float64(x, r):
357
+ r.extend((CHR_FLOAT64, struct.pack("!d", x)))
358
+
359
+
360
+ def encode_bool(x, r):
361
+ r.append({False: CHR_FALSE, True: CHR_TRUE}[bool(x)])
362
+
363
+
364
+ def encode_none(x, r):
365
+ r.append(CHR_NONE)
366
+
367
+
368
+ def encode_string(x, r):
369
+ if len(x) < STR_FIXED_COUNT:
370
+ r.extend((int2byte(STR_FIXED_START + len(x)), x))
371
+ else:
372
+ s = str(len(x))
373
+ if py3:
374
+ s = bytes(s, "ascii")
375
+ r.extend((s, b":", x))
376
+
377
+
378
+ def encode_unicode(x, r):
379
+ encode_string(x.encode("utf8"), r)
380
+
381
+
382
+ def encode_list(x, r):
383
+ if len(x) < LIST_FIXED_COUNT:
384
+ r.append(int2byte(LIST_FIXED_START + len(x)))
385
+ for i in x:
386
+ encode_func[type(i)](i, r)
387
+ else:
388
+ r.append(CHR_LIST)
389
+ for i in x:
390
+ encode_func[type(i)](i, r)
391
+ r.append(CHR_TERM)
392
+
393
+
394
+ def encode_dict(x, r):
395
+ if len(x) < DICT_FIXED_COUNT:
396
+ r.append(int2byte(DICT_FIXED_START + len(x)))
397
+ for k, v in x.items():
398
+ encode_func[type(k)](k, r)
399
+ encode_func[type(v)](v, r)
400
+ else:
401
+ r.append(CHR_DICT)
402
+ for k, v in x.items():
403
+ encode_func[type(k)](k, r)
404
+ encode_func[type(v)](v, r)
405
+ r.append(CHR_TERM)
406
+
407
+
408
+ encode_func = {}
409
+ encode_func[int] = encode_int
410
+ encode_func[long] = encode_int
411
+ encode_func[bytes] = encode_string
412
+ encode_func[list] = encode_list
413
+ encode_func[tuple] = encode_list
414
+ encode_func[dict] = encode_dict
415
+ encode_func[type(None)] = encode_none
416
+ encode_func[unicode] = encode_unicode
417
+ encode_func[bool] = encode_bool
418
+
419
+ lock = Lock()
420
+
421
+
422
+ def dumps(x, float_bits=DEFAULT_FLOAT_BITS):
423
+ """
424
+ Dump data structure to str.
425
+
426
+ Here float_bits is either 32 or 64.
427
+ """
428
+ with lock:
429
+ if float_bits == 32:
430
+ encode_func[float] = encode_float32
431
+ elif float_bits == 64:
432
+ encode_func[float] = encode_float64
433
+ else:
434
+ raise ValueError("Float bits (%d) is not 32 or 64" % float_bits)
435
+ r = []
436
+ encode_func[type(x)](x, r)
437
+ return b"".join(r)
438
+
439
+
440
+ def test():
441
+ f1 = struct.unpack("!f", struct.pack("!f", 25.5))[0]
442
+ f2 = struct.unpack("!f", struct.pack("!f", 29.3))[0]
443
+ f3 = struct.unpack("!f", struct.pack("!f", -0.6))[0]
444
+ ld = (
445
+ (
446
+ {b"a": 15, b"bb": f1, b"ccc": f2, b"": (f3, (), False, True, b"")},
447
+ (b"a", 10 ** 20),
448
+ tuple(range(-100000, 100000)),
449
+ b"b" * 31,
450
+ b"b" * 62,
451
+ b"b" * 64,
452
+ 2 ** 30,
453
+ 2 ** 33,
454
+ 2 ** 62,
455
+ 2 ** 64,
456
+ 2 ** 30,
457
+ 2 ** 33,
458
+ 2 ** 62,
459
+ 2 ** 64,
460
+ False,
461
+ False,
462
+ True,
463
+ -1,
464
+ 2,
465
+ 0,
466
+ ),
467
+ )
468
+ assert loads(dumps(ld)) == ld
469
+ d = dict(zip(range(-100000, 100000), range(-100000, 100000)))
470
+ d.update(
471
+ {b"a": 20, 20: 40, 40: 41, f1: f2, f2: f3, f3: False, False: True, True: False}
472
+ )
473
+ ld = (d, {}, {5: 6}, {7: 7, True: 8}, {9: 10, 22: 39, 49: 50, 44: b""})
474
+ assert loads(dumps(ld)) == ld
475
+ ld = (
476
+ b"",
477
+ b"a" * 10,
478
+ b"a" * 100,
479
+ b"a" * 1000,
480
+ b"a" * 10000,
481
+ b"a" * 100000,
482
+ b"a" * 1000000,
483
+ b"a" * 10000000,
484
+ )
485
+ assert loads(dumps(ld)) == ld
486
+ ld = tuple([dict(zip(range(n), range(n))) for n in range(100)]) + (b"b",)
487
+ assert loads(dumps(ld)) == ld
488
+ ld = tuple([dict(zip(range(n), range(-n, 0))) for n in range(100)]) + (b"b",)
489
+ assert loads(dumps(ld)) == ld
490
+ ld = tuple([tuple(range(n)) for n in range(100)]) + (b"b",)
491
+ assert loads(dumps(ld)) == ld
492
+ ld = tuple([b"a" * n for n in range(1000)]) + (b"b",)
493
+ assert loads(dumps(ld)) == ld
494
+ ld = tuple([b"a" * n for n in range(1000)]) + (None, True, None)
495
+ assert loads(dumps(ld)) == ld
496
+ assert loads(dumps(None)) is None
497
+ assert loads(dumps({None: None})) == {None: None}
498
+ assert 1e-10 < abs(loads(dumps(1.1)) - 1.1) < 1e-6
499
+ assert 1e-10 < abs(loads(dumps(1.1, 32)) - 1.1) < 1e-6
500
+ assert abs(loads(dumps(1.1, 64)) - 1.1) < 1e-12
501
+ assert loads(dumps("Hello World!!"), decode_utf8=True)
502
+
503
+
504
+ try:
505
+ import psyco
506
+
507
+ psyco.bind(dumps)
508
+ psyco.bind(loads)
509
+ except ImportError:
510
+ pass
511
+
512
+
513
+ if __name__ == "__main__":
514
+ test()