├── .travis.yml ├── COPYING ├── README.md ├── lzstring.py ├── setup.cfg ├── setup.py └── test.py /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "3.4" 4 | before_install: 5 | - pip install pytest pytest-cov 6 | - pip install coveralls 7 | script: 8 | - py.test 9 | after_success: 10 | - if [[ $ENV == python=3.4* ]]; then 11 | coveralls; 12 | fi 13 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | lz-string-python 2 | ================ 3 | 4 | master build status: 5 | [![Build Status](https://travis-ci.org/eduardtomasek/lz-string-python.svg?branch=master)](https://travis-ci.org/eduardtomasek/lz-string-python) 6 | 7 | lz-string for python 3 8 | 9 | Based on the LZ-String javascript found here: http://pieroxy.net/blog/pages/lz-string/index.html 10 | -------------------------------------------------------------------------------- /lzstring.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright © 2014 Eduard Tomasek 3 | This work is free. You can redistribute it and/or modify it under the 4 | terms of the Do What The Fuck You Want To Public License, Version 2, 5 | as published by Sam Hocevar. See the COPYING file for more details. 6 | """ 7 | 8 | import math 9 | import re 10 | 11 | 12 | class LZString: 13 | 14 | def __init__(self): 15 | self.keyStr = ( 16 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" 17 | ) 18 | 19 | @staticmethod 20 | def compress(uncompressed): 21 | 22 | if uncompressed is None: 23 | return '' 24 | 25 | value = 0 26 | context_dictionary = {} 27 | context_dictionaryToCreate = {} 28 | context_c = '' 29 | context_wc = '' 30 | context_w = '' 31 | context_enlargeIn = 2 32 | 33 | context_dictSize = 3 34 | context_numBits = 2 35 | context_data_string = '' 36 | context_data_val = 0 37 | context_data_position = 0 38 | 39 | uncompressed = uncompressed 40 | 41 | for ii in range(len(uncompressed)): 42 | context_c = uncompressed[ii] 43 | 44 | if context_c not in context_dictionary: 45 | context_dictionary[context_c] = context_dictSize 46 | context_dictSize += 1 47 | context_dictionaryToCreate[context_c] = True 48 | 49 | context_wc = context_w + context_c 50 | 51 | if context_wc in context_dictionary: 52 | context_w = context_wc 53 | else: 54 | if context_w in context_dictionaryToCreate: 55 | if ord(context_w[0]) < 256: 56 | for _ in range(context_numBits): 57 | context_data_val = (context_data_val << 1) 58 | 59 | if context_data_position == 15: 60 | context_data_position = 0 61 | context_data_string += chr(context_data_val) 62 | context_data_val = 0 63 | else: 64 | context_data_position += 1 65 | 66 | value = ord(context_w[0]) 67 | 68 | for i in range(8): 69 | context_data_val = ( 70 | (context_data_val << 1) | (value & 1) 71 | ) 72 | 73 | if context_data_position == 15: 74 | context_data_position = 0 75 | context_data_string += chr(context_data_val) 76 | context_data_val = 0 77 | else: 78 | context_data_position += 1 79 | 80 | value = value >> 1 81 | else: 82 | value = 1 83 | 84 | for i in range(context_numBits): 85 | context_data_val = (context_data_val << 1) | value 86 | 87 | if context_data_position == 15: 88 | context_data_position = 0 89 | context_data_string += chr(context_data_val) 90 | context_data_val = 0 91 | else: 92 | context_data_position += 1 93 | 94 | value = 0 95 | 96 | value = ord(context_w[0]) 97 | 98 | for i in range(16): 99 | context_data_val = ( 100 | (context_data_val << 1) | (value & 1) 101 | ) 102 | 103 | if context_data_position == 15: 104 | context_data_position = 0 105 | context_data_string += chr(context_data_val) 106 | context_data_val = 0 107 | else: 108 | context_data_position += 1 109 | 110 | value = value >> 1 111 | 112 | context_enlargeIn -= 1 113 | 114 | if context_enlargeIn == 0: 115 | context_enlargeIn = pow(2, context_numBits) 116 | context_numBits += 1 117 | 118 | context_dictionaryToCreate.pop(context_w, None) 119 | # del context_dictionaryToCreate[context_w] 120 | else: 121 | value = context_dictionary[context_w] 122 | 123 | for i in range(context_numBits): 124 | context_data_val = ( 125 | (context_data_val << 1) | (value & 1) 126 | ) 127 | 128 | if context_data_position == 15: 129 | context_data_position = 0 130 | context_data_string += chr(context_data_val) 131 | context_data_val = 0 132 | else: 133 | context_data_position += 1 134 | 135 | value = value >> 1 136 | 137 | context_enlargeIn -= 1 138 | 139 | if context_enlargeIn == 0: 140 | context_enlargeIn = pow(2, context_numBits) 141 | context_numBits += 1 142 | 143 | context_dictionary[context_wc] = context_dictSize 144 | context_dictSize += 1 145 | context_w = context_c 146 | if context_w != '': 147 | if context_w in context_dictionaryToCreate: 148 | if ord(context_w[0]) < 256: 149 | for i in range(context_numBits): 150 | context_data_val = (context_data_val << 1) 151 | 152 | if context_data_position == 15: 153 | context_data_position = 0 154 | context_data_string += chr(context_data_val) 155 | context_data_val = 0 156 | else: 157 | context_data_position += 1 158 | 159 | value = ord(context_w[0]) 160 | 161 | for i in range(8): 162 | context_data_val = ( 163 | (context_data_val << 1) | (value & 1) 164 | ) 165 | 166 | if context_data_position == 15: 167 | context_data_position = 0 168 | context_data_string += chr(context_data_val) 169 | context_data_val = 0 170 | else: 171 | context_data_position += 1 172 | 173 | value = value >> 1 174 | else: 175 | value = 1 176 | 177 | for i in range(context_numBits): 178 | context_data_val = (context_data_val << 1) | value 179 | 180 | if context_data_position == 15: 181 | context_data_position = 0 182 | context_data_string += chr(context_data_val) 183 | context_data_val = 0 184 | else: 185 | context_data_position += 1 186 | 187 | value = 0 188 | 189 | value = ord(context_w[0]) 190 | 191 | for i in range(16): 192 | context_data_val = ( 193 | (context_data_val << 1) | (value & 1) 194 | ) 195 | 196 | if context_data_position == 15: 197 | context_data_position = 0 198 | context_data_string += chr(context_data_val) 199 | context_data_val = 0 200 | else: 201 | context_data_position += 1 202 | 203 | value = value >> 1 204 | 205 | context_enlargeIn -= 1 206 | 207 | if context_enlargeIn == 0: 208 | context_enlargeIn = pow(2, context_numBits) 209 | context_numBits += 1 210 | 211 | context_dictionaryToCreate.pop(context_w, None) 212 | # del context_dictionaryToCreate[context_w] 213 | else: 214 | value = context_dictionary[context_w] 215 | 216 | for i in range(context_numBits): 217 | context_data_val = (context_data_val << 1) | (value & 1) 218 | 219 | if context_data_position == 15: 220 | context_data_position = 0 221 | context_data_string += chr(context_data_val) 222 | context_data_val = 0 223 | else: 224 | context_data_position += 1 225 | 226 | value = value >> 1 227 | 228 | context_enlargeIn -= 1 229 | 230 | if context_enlargeIn == 0: 231 | context_enlargeIn = pow(2, context_numBits) 232 | context_numBits += 1 233 | 234 | value = 2 235 | 236 | for i in range(context_numBits): 237 | context_data_val = (context_data_val << 1) | (value & 1) 238 | 239 | if context_data_position == 15: 240 | context_data_position = 0 241 | context_data_string += chr(context_data_val) 242 | context_data_val = 0 243 | else: 244 | context_data_position += 1 245 | 246 | value = value >> 1 247 | 248 | context_data_val = (context_data_val << 1) 249 | while context_data_position != 15: 250 | context_data_position += 1 251 | context_data_val = (context_data_val << 1) 252 | context_data_string += chr(context_data_val) 253 | 254 | return context_data_string 255 | 256 | def compressToBase64(self, string): 257 | if string is None: 258 | return '' 259 | 260 | output = '' 261 | 262 | chr1 = float('NaN') 263 | chr2 = float('NaN') 264 | chr3 = float('NaN') 265 | enc1 = 0 266 | enc2 = 0 267 | enc3 = 0 268 | enc4 = 0 269 | 270 | string = self.compress(string) 271 | strlen = len(string) 272 | 273 | for i in range(0, strlen * 2, 3): 274 | if (i % 2) == 0: 275 | chr1 = ord(string[i // 2]) >> 8 276 | chr2 = ord(string[i // 2]) & 255 277 | 278 | if (i / 2) + 1 < strlen: 279 | chr3 = ord(string[(i // 2) + 1]) >> 8 280 | else: 281 | chr3 = float('NaN') 282 | else: 283 | chr1 = ord(string[(i - 1) // 2]) & 255 284 | if (i + 1) / 2 < strlen: 285 | chr2 = ord(string[(i + 1) // 2]) >> 8 286 | chr3 = ord(string[(i + 1) // 2]) & 255 287 | else: 288 | chr2 = float('NaN') 289 | chr3 = float('NaN') 290 | 291 | # python dont support bit operation with NaN like javascript 292 | enc1 = chr1 >> 2 293 | enc2 = ( 294 | ((chr1 & 3) << 4) | 295 | (chr2 >> 4 if not math.isnan(chr2) else 0) 296 | ) 297 | enc3 = ( 298 | ((chr2 & 15 if not math.isnan(chr2) else 0) << 2) | 299 | (chr3 >> 6 if not math.isnan(chr3) else 0) 300 | ) 301 | enc4 = (chr3 if not math.isnan(chr3) else 0) & 63 302 | 303 | if math.isnan(chr2): 304 | enc3 = 64 305 | enc4 = 64 306 | elif math.isnan(chr3): 307 | enc4 = 64 308 | 309 | output += ( 310 | self.keyStr[enc1] + 311 | self.keyStr[enc2] + 312 | self.keyStr[enc3] + 313 | self.keyStr[enc4] 314 | ) 315 | 316 | return output 317 | 318 | def compressToUTF16(self, string): 319 | 320 | if string is None: 321 | return '' 322 | 323 | output = '' 324 | c = 0 325 | current = 0 326 | status = 0 327 | 328 | string = self.compress(string) 329 | 330 | for i in range(len(string)): 331 | c = ord(string[i]) 332 | 333 | if status == 0: 334 | status += 1 335 | output += chr(((c >> 1) + 32)) 336 | current = (c & 1) << 14 337 | elif status == 1: 338 | status += 1 339 | output += chr(((current + (c >> 2)) + 32)) 340 | current = (c & 3) << 13 341 | elif status == 2: 342 | status += 1 343 | output += chr(((current + (c >> 3)) + 32)) 344 | current = (c & 7) << 12 345 | elif status == 3: 346 | status += 1 347 | output += chr(((current + (c >> 4)) + 32)) 348 | current = (c & 15) << 11 349 | elif status == 4: 350 | status += 1 351 | output += chr(((current + (c >> 5)) + 32)) 352 | current = (c & 31) << 10 353 | elif status == 5: 354 | status += 1 355 | output += chr(((current + (c >> 6)) + 32)) 356 | current = (c & 63) << 9 357 | elif status == 6: 358 | status += 1 359 | output += chr(((current + (c >> 7)) + 32)) 360 | current = (c & 127) << 8 361 | elif status == 7: 362 | status += 1 363 | output += chr(((current + (c >> 8)) + 32)) 364 | current = (c & 255) << 7 365 | elif status == 8: 366 | status += 1 367 | output += chr(((current + (c >> 9)) + 32)) 368 | current = (c & 511) << 6 369 | elif status == 9: 370 | status += 1 371 | output += chr(((current + (c >> 10)) + 32)) 372 | current = (c & 1023) << 5 373 | elif status == 10: 374 | status += 1 375 | output += chr(((current + (c >> 11)) + 32)) 376 | current = (c & 2047) << 4 377 | elif status == 11: 378 | status += 1 379 | output += chr(((current + (c >> 12)) + 32)) 380 | current = (c & 4095) << 3 381 | elif status == 12: 382 | status += 1 383 | output += chr(((current + (c >> 13)) + 32)) 384 | current = (c & 8191) << 2 385 | elif status == 13: 386 | status += 1 387 | output += chr(((current + (c >> 14)) + 32)) 388 | current = (c & 16383) << 1 389 | elif status == 14: 390 | status += 1 391 | output += chr(((current + (c >> 15)) + 32)) 392 | output += chr((c & 32767) + 32) 393 | 394 | status = 0 395 | 396 | output += chr(current + 32) 397 | 398 | return output 399 | 400 | # written by https://github.com/v-python 401 | def decompressFromUTF16(self, string): 402 | if not string: 403 | return "" 404 | 405 | output = "" 406 | status = 0 407 | 408 | for i, k in enumerate(string): 409 | c = ord(k) - 32 410 | 411 | if status == 0: 412 | status = 1 413 | current = c << 1 414 | elif status == 1: 415 | status = 2 416 | output += chr(current + (c >> 14)) 417 | current = (c & 16383) << 2 418 | elif status == 2: 419 | status = 3 420 | output += chr(current + (c >> 13)) 421 | current = (c & 8191) << 3 422 | elif status == 3: 423 | status = 4 424 | output += chr(current + (c >> 12)) 425 | current = (c & 4095) << 4 426 | elif status == 4: 427 | status = 5 428 | output += chr(current + (c >> 11)) 429 | current = (c & 2047) << 5 430 | elif status == 5: 431 | status = 6 432 | output += chr(current + (c >> 10)) 433 | current = (c & 1023) << 6 434 | elif status == 6: 435 | status = 7 436 | output += chr(current + (c >> 9)) 437 | current = (c & 511) << 7 438 | elif status == 7: 439 | status = 8 440 | output += chr(current + (c >> 8)) 441 | current = (c & 255) << 8 442 | elif status == 8: 443 | status = 9 444 | output += chr(current + (c >> 7)) 445 | current = (c & 127) << 9 446 | elif status == 9: 447 | status = 10 448 | output += chr(current + (c >> 6)) 449 | current = (c & 63) << 10 450 | elif status == 10: 451 | status = 11 452 | output += chr(current + (c >> 5)) 453 | current = (c & 31) << 11 454 | elif status == 11: 455 | status = 12 456 | output += chr(current + (c >> 4)) 457 | current = (c & 15) << 12 458 | elif status == 12: 459 | status = 13 460 | output += chr(current + (c >> 3)) 461 | current = (c & 7) << 13 462 | elif status == 13: 463 | status = 14 464 | output += chr(current + (c >> 2)) 465 | current = (c & 3) << 14 466 | elif status == 14: 467 | status = 15 468 | output += chr(current + (c >> 1)) 469 | current = (c & 1) << 15 470 | elif status == 15: 471 | status = 0 472 | output += chr(current + c) 473 | current = (c & 1) << 15 474 | 475 | return self.decompress(output) 476 | 477 | @staticmethod 478 | def decompress(compressed): 479 | 480 | if (compressed is None) or (compressed == ''): 481 | return '' 482 | 483 | dictionary = {} 484 | enlargeIn = 4 485 | dictSize = 4 486 | numBits = 3 487 | (entry, result, w, c) = ('', '', '', '') 488 | (i, nnext, bits, resb, maxpower, power) = (0, 0, 0, 0, 0, 0) 489 | 490 | data_string = compressed 491 | data_val = ord(compressed[0]) 492 | data_position = 32768 493 | data_index = 1 494 | 495 | for i in range(3): 496 | # dictionary[i] = i 497 | dictionary[i] = '' 498 | 499 | bits = 0 500 | maxpower = pow(2, 2) 501 | power = 1 502 | 503 | while power != maxpower: 504 | resb = data_val & data_position 505 | data_position >>= 1 506 | 507 | if data_position == 0: 508 | data_position = 32768 509 | data_val = ord(data_string[data_index]) 510 | data_index += 1 511 | 512 | bits |= (1 if resb > 0 else 0) * power 513 | power <<= 1 514 | 515 | nnext = bits 516 | if nnext == 0: 517 | bits = 0 518 | maxpower = pow(2, 8) 519 | power = 1 520 | 521 | while power != maxpower: 522 | resb = data_val & data_position 523 | data_position >>= 1 524 | 525 | if data_position == 0: 526 | data_position = 32768 527 | data_val = ord(data_string[data_index]) 528 | data_index += 1 529 | 530 | bits |= (1 if resb > 0 else 0) * power 531 | power <<= 1 532 | 533 | c = chr(bits) 534 | elif nnext == 1: 535 | bits = 0 536 | maxpower = pow(2, 16) 537 | power = 1 538 | 539 | while power != maxpower: 540 | resb = data_val & data_position 541 | data_position >>= 1 542 | 543 | if data_position == 0: 544 | data_position = 32768 545 | data_val = ord(data_string[data_index]) 546 | data_index += 1 547 | 548 | bits |= (1 if resb > 0 else 0) * power 549 | power <<= 1 550 | 551 | c = chr(bits) 552 | elif nnext == 2: 553 | return '' 554 | 555 | dictionary[3] = c 556 | result = c 557 | w = result 558 | 559 | while True: 560 | if data_index > len(data_string): 561 | return '' 562 | 563 | bits = 0 564 | maxpower = pow(2, numBits) 565 | power = 1 566 | 567 | while power != maxpower: 568 | resb = data_val & data_position 569 | data_position >>= 1 570 | 571 | if data_position == 0: 572 | data_position = 32768 573 | data_val = ord(data_string[data_index]) 574 | data_index += 1 575 | 576 | bits |= (1 if resb > 0 else 0) * power 577 | power <<= 1 578 | 579 | c = bits 580 | 581 | if c == 0: 582 | bits = 0 583 | maxpower = pow(2, 8) 584 | power = 1 585 | 586 | while power != maxpower: 587 | resb = data_val & data_position 588 | data_position >>= 1 589 | 590 | if data_position == 0: 591 | data_position = 32768 592 | data_val = ord(data_string[data_index]) 593 | data_index += 1 594 | 595 | bits |= (1 if resb > 0 else 0) * power 596 | power <<= 1 597 | 598 | dictionary[dictSize] = chr(bits) 599 | dictSize += 1 600 | c = dictSize - 1 601 | enlargeIn -= 1 602 | elif c == 1: 603 | bits = 0 604 | maxpower = pow(2, 16) 605 | power = 1 606 | 607 | while power != maxpower: 608 | resb = data_val & data_position 609 | data_position >>= 1 610 | 611 | if data_position == 0: 612 | data_position = 32768 613 | data_val = ord(data_string[data_index]) 614 | data_index += 1 615 | 616 | bits |= (1 if resb > 0 else 0) * power 617 | power <<= 1 618 | 619 | dictionary[dictSize] = chr(bits) 620 | dictSize += 1 621 | c = dictSize - 1 622 | enlargeIn -= 1 623 | elif c == 2: 624 | return result 625 | 626 | if enlargeIn == 0: 627 | enlargeIn = pow(2, numBits) 628 | numBits += 1 629 | 630 | if c in dictionary: 631 | entry = dictionary[c] 632 | else: 633 | if c == dictSize: 634 | entry = w + w[0] 635 | else: 636 | return None 637 | 638 | result += entry 639 | 640 | dictionary[dictSize] = w + entry[0] 641 | dictSize += 1 642 | enlargeIn -= 1 643 | 644 | w = entry 645 | 646 | if enlargeIn == 0: 647 | enlargeIn = pow(2, numBits) 648 | numBits += 1 649 | 650 | def decompresFromBase64(self, iinput): 651 | if iinput is None: 652 | return '' 653 | 654 | output = "" 655 | ol = 0 656 | output_ = '' 657 | 658 | i = 0 659 | 660 | iinput = re.sub(r'[^A-Za-z0-9\+\/\=]', '', iinput) 661 | 662 | for i in range(0, len(iinput), 4): 663 | enc1, enc2, enc3, enc4 = ( 664 | self.keyStr.index(iinput[i]), 665 | self.keyStr.index(iinput[i+1]), 666 | self.keyStr.index(iinput[i+2]), 667 | self.keyStr.index(iinput[i+3]), 668 | ) 669 | 670 | chr1 = (enc1 << 2) | (enc2 >> 4) 671 | chr2 = ((enc2 & 15) << 4) | (enc3 >> 2) 672 | chr3 = ((enc3 & 3) << 6) | enc4 673 | 674 | if (ol % 2) == 0: 675 | output_ = chr1 << 8 676 | 677 | if enc3 != 64: 678 | output += chr(output_ | chr2) 679 | 680 | if enc4 != 64: 681 | output_ = chr3 << 8 682 | else: 683 | output = output + chr(output_ | chr1) 684 | 685 | if enc3 != 64: 686 | output_ = chr2 << 8 687 | 688 | if enc4 != 64: 689 | output += chr(output_ | chr3) 690 | 691 | ol += 3 692 | 693 | return self.decompress(output) 694 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [pytest] 2 | addopts = --cov-report term-missing --cov . 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | INSTALL_REQUIRES = [ 4 | ] 5 | 6 | ENTRY_POINTS = dict( 7 | console_scripts=[ 8 | ], 9 | ) 10 | 11 | setup( 12 | name='lz-string', 13 | version='0.1', 14 | long_description=__doc__, 15 | packages=find_packages(), 16 | include_package_data=True, 17 | zip_safe=False, 18 | license='WTFPL', 19 | author='Eduard Tomasek', 20 | url='https://gitlab.com/eduardtomasek/lz-string-python/', 21 | install_requires=INSTALL_REQUIRES, 22 | entry_points=ENTRY_POINTS, 23 | ) 24 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright © 2014 Eduard Tomasek 3 | This work is free. You can redistribute it and/or modify it under the 4 | terms of the Do What The Fuck You Want To Public License, Version 2, 5 | as published by Sam Hocevar. See the COPYING file for more details. 6 | """ 7 | 8 | import json 9 | import lzstring 10 | import pprint 11 | 12 | 13 | if __name__ == '__main__': 14 | x = lzstring.LZString() 15 | 16 | s = 'Žluťoučký kůň úpěl ďábelské ódy!' 17 | 18 | # generated with original js lib 19 | jsLzStringBase64 = 'r6ABsK6KaAD2aLCADWBfgBPQ9oCAlAZAvgDobEARlB4QAEOAjAUxAGd4BL5AZ4BMBPAQiAAA' 20 | jsLzStringBase64Json = 'N4Ig5gNg9gzjCGAnAniAXKALgS0xApuiPgB7wC2ADgQASSwIogA0IA4tHACLYBu6WXASIBlFu04wAMthiYBEhgFEAdpiYYQASS6i2AWSniRURJgCCMPYfEcGAFXyJyozPBUATJB5pt8Kp3gIbAAvfB99JABrAFdKGil3MBj4MEJWcwBjRCgVZBc0EBEDIwyAIzLEfH5CrREAeRoADiaAdgBONABGdqaANltJLnwAMwVKJHgicxpyfDcAWnJouJoIJJS05hoYmHCaTCgabPx4THxZlfj1lWTU/BgaGBjMgAsaeEeuKEyAISgoFEAHSDBgifD4cwQGBQdAAbXYNlYAA0bABdAC+rDscHBhEKy0QsUoIAxZLJQAAA==' 21 | 22 | print('String for encode: ' + s) 23 | print() 24 | 25 | print('Compress to base64:') 26 | base2 = x.compressToBase64(s) 27 | print('result: ' + base2) 28 | print('result js: ' + jsLzStringBase64) 29 | print('equals: ' + str(base2 == jsLzStringBase64)) 30 | 31 | print() 32 | 33 | print('Decompress from base64:') 34 | print('result: ' + x.decompresFromBase64(base2)) 35 | print('result from js: ' + x.decompresFromBase64(jsLzStringBase64)) 36 | 37 | print() 38 | 39 | jsonString = '{"glossary":{"title":"example glossary","GlossDiv":{"title":"S","GlossList":{"GlossEntry":{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML"]},"GlossSee":"markup"}}}}}' 40 | 41 | print('Compress json to base64:') 42 | jresult = x.compressToBase64(jsonString) 43 | print('result: ' + jresult) 44 | print() 45 | print('result js: ' + jsLzStringBase64Json) 46 | print() 47 | print('equals: ' + str(jresult == jsLzStringBase64Json)) 48 | 49 | print() 50 | 51 | print('Decompress json from base64:') 52 | pprint.pprint(json.loads(x.decompresFromBase64(jsLzStringBase64Json))) 53 | --------------------------------------------------------------------------------