py2ls 0.2.4.33__tar.gz → 0.2.4.35__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (260) hide show
  1. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/PKG-INFO +7 -3
  2. py2ls-0.2.4.35/py2ls/data/RealESRGAN_x4plus.pth +0 -0
  3. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/ips.py +391 -61
  4. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/netfinder.py +30 -40
  5. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/ocr.py +4 -5
  6. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/pyproject.toml +7 -3
  7. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/README.md +0 -0
  8. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.DS_Store +0 -0
  9. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/.DS_Store +0 -0
  10. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/COMMIT_EDITMSG +0 -0
  11. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/FETCH_HEAD +0 -0
  12. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/HEAD +0 -0
  13. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/config +0 -0
  14. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/description +0 -0
  15. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/hooks/applypatch-msg.sample +0 -0
  16. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/hooks/commit-msg.sample +0 -0
  17. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/hooks/fsmonitor-watchman.sample +0 -0
  18. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/hooks/post-update.sample +0 -0
  19. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/hooks/pre-applypatch.sample +0 -0
  20. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/hooks/pre-commit.sample +0 -0
  21. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/hooks/pre-merge-commit.sample +0 -0
  22. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/hooks/pre-push.sample +0 -0
  23. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/hooks/pre-rebase.sample +0 -0
  24. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/hooks/pre-receive.sample +0 -0
  25. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/hooks/prepare-commit-msg.sample +0 -0
  26. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/hooks/push-to-checkout.sample +0 -0
  27. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/hooks/update.sample +0 -0
  28. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/index +0 -0
  29. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/info/exclude +0 -0
  30. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/logs/HEAD +0 -0
  31. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/logs/refs/heads/main +0 -0
  32. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/logs/refs/remotes/origin/HEAD +0 -0
  33. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/logs/refs/remotes/origin/main +0 -0
  34. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/.DS_Store +0 -0
  35. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/01/d5bd8065e6860c0bd23ff9fa57161806a099e1 +0 -0
  36. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/09/08da26de58c114225ad81f484b80bf5d351b34 +0 -0
  37. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/0b/409e1bc918277010f5679b402d1d1dda53e15c +0 -0
  38. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/12/c2808a1b3a4d0892a4154dfba1e2ae3770fa73 +0 -0
  39. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/14/449a0e6ba4ea2f1a73acf63ef91c9c6193f9ed +0 -0
  40. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/15/a8e468aacfcb440e090020f36d0b985d45da23 +0 -0
  41. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/1a/b4585881a6a42889f01aa0cfe25fd5acfaf46f +0 -0
  42. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/1c/3f92adda34344bcbbbf9d409c79855ae2aaea8 +0 -0
  43. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/1c/9314c5f69b9390068a2a8616875d974849d71f +0 -0
  44. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/1d/fe9d9633b24ea560354f4f93d39c6e5f163ea0 +0 -0
  45. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/20/72c28e83f4347959d29f7b3a6c1fc3e4ee6b59 +0 -0
  46. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/24/6b368b986f758630c46dc02b7fa512b53422f7 +0 -0
  47. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/25/b796accd261b9135fd32a2c00785f68edf6c46 +0 -0
  48. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/27/aa6074f652bc6f7078f8647489d9ee8e24f0e2 +0 -0
  49. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/28/c2969d785c1b892c2a96b3f00eba63a59811b3 +0 -0
  50. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/2a/ae95d517d213b660bf4f65a4e0cfae7bb893eb +0 -0
  51. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/2a/fdf45791a26d42ccead35ace76a8f0b2a56561 +0 -0
  52. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/30/a2f8da47ee947811dc8d993f5a06a45de374f4 +0 -0
  53. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/32/fd627b62fad7cf3b2f9e34ab9777126a0987ad +0 -0
  54. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/34/9e31b6a3634cea102ce5588b98c11cc1738605 +0 -0
  55. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/34/b6f3a2ee84f39bed4eee57f2c0e0afb994feb1 +0 -0
  56. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/35/1a5f491ab97eee9d1ee699478d75a8bb5d3dc2 +0 -0
  57. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/36/b4a1b7403abc6c360f8fe2cb656ab945254971 +0 -0
  58. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/36/e56a361f526eafa59c5235a5c990bf288b5f9c +0 -0
  59. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/36/ef43e50009e59db11812c258846d9e38718173 +0 -0
  60. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/39/7ead045fbbcfb17c62019eb18fe21ed05dbee5 +0 -0
  61. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/39/b13be65125556784e44c7a1d9821703c7ab67e +0 -0
  62. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/3b/507acc7f23391644cc0b824b1e79fd2677a362 +0 -0
  63. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/3b/bd972aa7ad680858f8dfbd0f7fcd97756f0d6f +0 -0
  64. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/3c/bbe5f4173d165127b9ad96119f1ec24c306ffc +0 -0
  65. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/3d/9d10d27724657a436c65a6254bfd213d4b3562 +0 -0
  66. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/3f/d6561300938afbb3d11976cf9c8f29549280d9 +0 -0
  67. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/41/dcf4b3bf0460946b2da93776cf9e836d62178f +0 -0
  68. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/43/dbd49b2ee367c5434dd545e3b5795434f2ef0b +0 -0
  69. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/45/b1b6178bacbfc997811a998b5cc60c1ea7fac8 +0 -0
  70. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/47/6cbd5a7c5e35cddef2f8a38bdc4896d403b095 +0 -0
  71. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/48/a88fc5806305d0bb0755ee6801161b79696972 +0 -0
  72. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/4f/7afb40dff2153d857fc85748c2eecb85125042 +0 -0
  73. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/50/08ddfcf53c02e82d7eee2e57c38e5672ef89f6 +0 -0
  74. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/53/e0deb1cb4c2c606bced6e7f9a66b0fda60980d +0 -0
  75. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/56/e4e8b2d5545e0256090f45aa8fc42c5fe067d0 +0 -0
  76. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/57/63d0c52f5c9c69e89d514a1f96034947abe21a +0 -0
  77. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/57/bd1c0199483ab316235b094543b85edec6c35e +0 -0
  78. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/58/20a729045d4dc7e37ccaf8aa8eec126850afe2 +0 -0
  79. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/59/380c4c26bdcd4d9b71ae3e2e35f05b3f26c5ab +0 -0
  80. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/5a/192565abf89c9d765af846ce6d53a92b1ce7ad +0 -0
  81. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/60/f273eb1c412d916fa3f11318a7da7a9911b52a +0 -0
  82. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/61/570cec8c061abe74121f27f5face6c69b98f99 +0 -0
  83. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/62/4488173ed2c8936fa5cea3cf5dd3f26a30b86e +0 -0
  84. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/62/7c81b23b4e56e87b042b650b0103653cc9e34a +0 -0
  85. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/62/d90ccf8cbefdc2e4fd475e7c6f4f76e9fdf801 +0 -0
  86. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/63/100154b27846e8010e55b6bf4b3d7762c14c5f +0 -0
  87. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/64/27a4edff08f93d98f511418423f09f2ab90bcd +0 -0
  88. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/66/6227eeeba24073e63811e89f1449f3d958f183 +0 -0
  89. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/66/c998778721d424bd0aae80602dabbffa93af2e +0 -0
  90. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/68/6df3072c8b025fb18106ed2df505994ad062a9 +0 -0
  91. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/69/13c452ca319f7cbf6a0836dc10a5bb033c84e4 +0 -0
  92. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/6a/52e747a2b349b128d1490d9e896d2323818eb7 +0 -0
  93. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/6b/7fde264d93a7a0986d394c46c7650d0ce2ab92 +0 -0
  94. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/6c/cebb29b7f3f5b0c889f6dadbf9ff066554587d +0 -0
  95. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/6d/c2cdf4a84e538e5d4777486aeff87e42f41799 +0 -0
  96. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/6d/ee29dbdcc84edeeacede105110446f3ccac963 +0 -0
  97. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/71/36b2074a2754be8b58127d82250e5b37e3c373 +0 -0
  98. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/72/245a05b0966011cb381e6b32b0465000e969ab +0 -0
  99. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/72/e4179337639859678ddaecf38b16f33aaec8e1 +0 -0
  100. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/78/063f4c863fc371ec0313303c0a81283b35d9b6 +0 -0
  101. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/78/3d4167bc95c9d2175e0df03ef1c1c880ba75ab +0 -0
  102. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/79/7ae089b2212a937840e215276005ce76881307 +0 -0
  103. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/7e/5956c806b5edc344d46dab599dec337891ba1f +0 -0
  104. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/81/8f26b7bf042269729020cf944fc362d66ba27e +0 -0
  105. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/82/70b319ce4046854fbe7dc41054b6c2d112dab2 +0 -0
  106. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/84/59071b722a255b774a80b27746033f8141ab39 +0 -0
  107. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/85/aee46f478e9afdb84d50a05242c53b04ed2e21 +0 -0
  108. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/86/e288b46f8fe179907e4413f665aeb5053fddb1 +0 -0
  109. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/87/ef1fc3f7f1ddc4d0ab9b3e65381ce9f3388621 +0 -0
  110. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/8b/84f56978e1de8f2ae82abce5f8b3e182d365cd +0 -0
  111. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/8e/55a7d2b96184030211f20c9b9af201eefcac82 +0 -0
  112. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/91/c69ad88fe0ba94aa7859fb5f7edac5e6f1a3f7 +0 -0
  113. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/94/74152b4b463d70ae5ad07f0c658be3e296026b +0 -0
  114. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/94/f7dbe88e80c4205a901b71eb8f181974376bba +0 -0
  115. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/97/1aef09ea939f46b60b9646f8d524c78a9220f4 +0 -0
  116. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/9b/ec5ee2236ee2d5532c36bfd132e23c58fdb69c +0 -0
  117. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/9d/0df52899fe95279059286d9c0ec42287edc168 +0 -0
  118. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/a1/5389729850729fc7bd78a54f26fce77f30be12 +0 -0
  119. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/a1/906da89d1174f74867800c74c43af36253bd5e +0 -0
  120. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/a4/63fdd23e5efd713db8a71f316f3a1c7bd60916 +0 -0
  121. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/a5/ec8f74642fbba27f7ea78c53b372ae0c7dedce +0 -0
  122. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/a7/3e13eafee65c5b8d73ad2d3ea46d0eee82f0d3 +0 -0
  123. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/b0/56be4be89ba6b76949dd641df45bb7036050c8 +0 -0
  124. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/b0/9cd7856d58590578ee1a4f3ad45d1310a97f87 +0 -0
  125. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/b2/18e6a0f0f1c4df8cdefa9852058348abc713b7 +0 -0
  126. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/b3/4f7f271c6d6105e35a6556ffda71d03afe8c96 +0 -0
  127. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/b3/69579064bde9de9a19d114fc33e4e48cc8c0e4 +0 -0
  128. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/b5/61831c7dce8ea51e7ee6b6fa35745f14d8242d +0 -0
  129. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/b7/2c9e75ab7d0afe594664650aa8f6c772f5ac64 +0 -0
  130. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/bb/81ccc0513f18fc160b54a82861e9a80d23f4f6 +0 -0
  131. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/bb/934eb33bc1a8b85630bf680caffd99560c1b8f +0 -0
  132. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/bf/67907e337021ebff434e02b19b30a741c144af +0 -0
  133. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/bf/b54d65922ce1dfda1aaa014913a54e7172d0bc +0 -0
  134. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/c1/20fc812b9ad311c34a3608512d6a9d976bb48e +0 -0
  135. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/c1/397c6ed72c4e20ef6b9ab83163e9a6baba5b45 +0 -0
  136. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/c4/cba65f1163661999ee4b8ed23342b63bc1300c +0 -0
  137. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/c6/7f17e5707313600efcb85e9a3fedea35dba591 +0 -0
  138. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/c6/f32aced880bd165a251cb52b26b0c1107e2141 +0 -0
  139. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/cc/45df1d317a2eb63ff1ff3a5f3b4a9f98fd92b5 +0 -0
  140. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/cd/822b3574a88ebdd1ed82fd6983f37e626d52b4 +0 -0
  141. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/cf/0c0d9c6fb09473aaeb7f7e2edbd770c3f2ef3d +0 -0
  142. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/d2/992df305f4b56a466a2f221aeb182ddd20f418 +0 -0
  143. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/d6/39e8af592cd75a318d8affddd1bcc70c2095f2 +0 -0
  144. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/d6/9ab1c4aadf279936dd778e8346ba60f74705b6 +0 -0
  145. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/d8/4688b54c0040a30976b3a6540bc47adf7ce680 +0 -0
  146. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/d9/005f2cc7fc4e65f14ed5518276007c08cf2fd0 +0 -0
  147. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/d9/c2403fd166ce791b4e9d0c6792ed8342c71fcd +0 -0
  148. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/d9/dfa5aee51e92a541b707e8e7baea6f06deff98 +0 -0
  149. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/db/141dbaa93594df2a8156182f361ee4db829359 +0 -0
  150. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/db/3f2cd643292057936230b95cf7ec3046affe11 +0 -0
  151. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/db/ffa8ea7bda721d0cee7b9e4ce5b2ef927733ff +0 -0
  152. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/dc/c2bdbafb3296e09d9ee4955cfa55d275825f94 +0 -0
  153. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/dc/cdbd4266765d840be2ae35ab1752a0fa312c16 +0 -0
  154. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/dd/87fb5f606fe380d81e6fe3a2c98f9f99e3e09b +0 -0
  155. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/de/214c626ac2dd2685bfaa0bc0fc20f528d014d7 +0 -0
  156. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/df/e0770424b2a19faf507a501ebfc23be8f54e7b +0 -0
  157. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/e2/f2f8f4c25e62a297fc55f36acc6b01cfbab76f +0 -0
  158. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/e3/1356f90ea6dd0577b5e0b40b206319adcbf085 +0 -0
  159. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/e3/5a4dafc50850cacac7bf76c56db2715cbda2c4 +0 -0
  160. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/e4/6c715352db9fe3c887a635f1916df4ca1f4ff9 +0 -0
  161. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/e5/0580a0bd1e1b3d29f834382b80fceb61d5cf0c +0 -0
  162. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/e9/391ffe371f1cc43b42ef09b705d9c767c2e14f +0 -0
  163. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/ea/3a18cc75e53792744ef754e05d3f4481768c13 +0 -0
  164. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/ec/40fd8bf8e4c342534a9fc020289e402ba6bc9d +0 -0
  165. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/ec/d980279432b13f0374b90ca439a6329cdece0f +0 -0
  166. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/ee/cee64eacaff022dcdc509c0c2b1da492f21060 +0 -0
  167. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/f1/e50757fddc28b445545dc7e2759b54cdd0f42e +0 -0
  168. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/f4/b64d3107b39e3ad6f540c6607004ea34e6c024 +0 -0
  169. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/f4/ba7f815b886797b73fede071d86e0c134d2bc7 +0 -0
  170. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/f5/61c3c1bf1c9ea9c9d1f556a7be2869f71f3bdf +0 -0
  171. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/f6/44a8ff56fa035105fc517cbb1ac46c3d8e349a +0 -0
  172. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/f7/c98ba5c2f903e603b1f5e63d49fbc8a43815cc +0 -0
  173. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/f9/045a08e96eb76848fc4d68e3e3e687cca39a2d +0 -0
  174. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/fa/147e6bb78a2e8db241d231295fd7f1ed061af8 +0 -0
  175. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/objects/fc/292e793ecfd42240ac43be407023bd731fa9e7 +0 -0
  176. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/refs/.DS_Store +0 -0
  177. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/refs/heads/main +0 -0
  178. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/refs/remotes/origin/HEAD +0 -0
  179. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.git/refs/remotes/origin/main +0 -0
  180. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.gitattributes +0 -0
  181. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/.gitignore +0 -0
  182. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/LICENSE +0 -0
  183. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/README.md +0 -0
  184. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/__init__.py +0 -0
  185. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/batman.py +0 -0
  186. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/bio.py +0 -0
  187. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/brain_atlas.py +0 -0
  188. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/chat.py +0 -0
  189. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/corr.py +0 -0
  190. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/correlators.py +0 -0
  191. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/.DS_Store +0 -0
  192. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/db2ls_sql_chtsht.json +0 -0
  193. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/docs_links.json +0 -0
  194. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/email/email_html_template.html +0 -0
  195. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/hyper_param_autogluon_zeroshot2024.json +0 -0
  196. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/hyper_param_tabrepo_2024.py +0 -0
  197. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/lang_code_iso639.json +0 -0
  198. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/mygenes_fields_241022.txt +0 -0
  199. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/sns_info.json +0 -0
  200. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/.DS_Store +0 -0
  201. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/example/.DS_Store +0 -0
  202. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/example/style1.pdf +0 -0
  203. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/example/style2.pdf +0 -0
  204. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/example/style3.pdf +0 -0
  205. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/example/style4.pdf +0 -0
  206. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/example/style5.pdf +0 -0
  207. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/example/style6.pdf +0 -0
  208. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/example/style7.pdf +0 -0
  209. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/example/style8.pdf +0 -0
  210. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/example/style9.pdf +0 -0
  211. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/style1.json +0 -0
  212. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/style10.json +0 -0
  213. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/style11.json +0 -0
  214. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/style12.json +0 -0
  215. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/style2.json +0 -0
  216. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/style3.json +0 -0
  217. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/style4.json +0 -0
  218. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/style5.json +0 -0
  219. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/style6.json +0 -0
  220. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/style7.json +0 -0
  221. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/style8.json +0 -0
  222. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/style9.json +0 -0
  223. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/.DS_Store +0 -0
  224. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/grid.mplstyle +0 -0
  225. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/high-contrast.mplstyle +0 -0
  226. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/high-vis.mplstyle +0 -0
  227. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/ieee.mplstyle +0 -0
  228. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/light.mplstyl +0 -0
  229. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/muted.mplstyle +0 -0
  230. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/nature-reviews-latex.mplstyle +0 -0
  231. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/nature-reviews.mplstyle +0 -0
  232. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/nature.mplstyle +0 -0
  233. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/no-latex.mplstyle +0 -0
  234. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/notebook.mplstyle +0 -0
  235. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/paper.mplstyle +0 -0
  236. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/retro.mplstyle +0 -0
  237. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/sans.mplstyle +0 -0
  238. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/scatter.mplstyle +0 -0
  239. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/science.mplstyle +0 -0
  240. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/std-colors.mplstyle +0 -0
  241. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/vibrant.mplstyle +0 -0
  242. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/tiles.csv +0 -0
  243. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/usages_pd.json +0 -0
  244. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/data/usages_sns.json +0 -0
  245. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/db2ls.py +0 -0
  246. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/doc.py +0 -0
  247. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/ec2ls.py +0 -0
  248. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/export_requirements.py +0 -0
  249. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/fetch_update.py +0 -0
  250. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/freqanalysis.py +0 -0
  251. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/ich2ls.py +0 -0
  252. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/ml2ls.py +0 -0
  253. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/mol.py +0 -0
  254. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/nl2ls.py +0 -0
  255. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/plot.py +0 -0
  256. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/setuptools-70.1.0-py3-none-any.whl +0 -0
  257. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/sleep_events_detectors.py +0 -0
  258. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/stats.py +0 -0
  259. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/translator.py +0 -0
  260. {py2ls-0.2.4.33 → py2ls-0.2.4.35}/py2ls/wb_detector.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: py2ls
3
- Version: 0.2.4.33
3
+ Version: 0.2.4.35
4
4
  Summary: py(thon)2(too)ls
5
5
  Author: Jianfeng
6
6
  Author-email: Jianfeng.Liu0413@gmail.com
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3.9
14
14
  Classifier: Programming Language :: Python :: 3.10
15
15
  Classifier: Programming Language :: Python :: 3.11
16
16
  Classifier: Programming Language :: Python :: 3.12
17
- Provides-Extra: extr
17
+ Provides-Extra: full
18
18
  Requires-Dist: CacheControl (>=0.13.1)
19
19
  Requires-Dist: Cython (>=3.0.10)
20
20
  Requires-Dist: Deprecated (>=1.2.14)
@@ -85,7 +85,7 @@ Requires-Dist: h2 (>=3.2.0)
85
85
  Requires-Dist: h5py (>=3.11.0)
86
86
  Requires-Dist: hpack (>=3.0.0)
87
87
  Requires-Dist: hstspreload (>=2024.7.1)
88
- Requires-Dist: httpcore (>=0.9.1)
88
+ Requires-Dist: httpcore (>=0.9.0)
89
89
  Requires-Dist: httpx (>=0.13.3)
90
90
  Requires-Dist: humanfriendly (>=10.0)
91
91
  Requires-Dist: hyperframe (>=5.2.0)
@@ -123,6 +123,7 @@ Requires-Dist: mne (>=1.7.1)
123
123
  Requires-Dist: more-itertools (>=10.3.0)
124
124
  Requires-Dist: mpmath (>=1.3.0)
125
125
  Requires-Dist: msgpack (>=1.0.8)
126
+ Requires-Dist: msoffcrypto-tool (>=5.4.2)
126
127
  Requires-Dist: mtscomp (>=1.0.2)
127
128
  Requires-Dist: nbclient (>=0.10.0)
128
129
  Requires-Dist: nbconvert (>=7.16.4)
@@ -131,6 +132,7 @@ Requires-Dist: neo (>=0.13.1)
131
132
  Requires-Dist: nest-asyncio (>=1.6.0)
132
133
  Requires-Dist: networkx (>=3.3)
133
134
  Requires-Dist: nltk (>=3.8.1)
135
+ Requires-Dist: nuitka (>=2.5.9)
134
136
  Requires-Dist: numba (>=0.59.1)
135
137
  Requires-Dist: numcodecs (>=0.13.0)
136
138
  Requires-Dist: numerizer (>=0.2.3)
@@ -139,6 +141,7 @@ Requires-Dist: onnxruntime (>=1.18.1)
139
141
  Requires-Dist: opencv-contrib-python (>=4.10.0.84)
140
142
  Requires-Dist: opencv-python (>=4.10.0.84)
141
143
  Requires-Dist: opencv-python-headless (>=4.10.0.84)
144
+ Requires-Dist: openpyxl (>=3.1.5)
142
145
  Requires-Dist: outcome (>=1.3.0.post0)
143
146
  Requires-Dist: packaging (>=24.1)
144
147
  Requires-Dist: pandas (>=2.2.2)
@@ -199,6 +202,7 @@ Requires-Dist: rpds-py (>=0.18.1)
199
202
  Requires-Dist: scikit-image (>=0.23.2)
200
203
  Requires-Dist: scikit-learn (>=1.5.1)
201
204
  Requires-Dist: scipy (>=1.14.0)
205
+ Requires-Dist: scrapy (>=2.12.0)
202
206
  Requires-Dist: seaborn (>=0.13.2)
203
207
  Requires-Dist: selenium (>=4.23.1)
204
208
  Requires-Dist: setuptools (>=70.3.0)
@@ -26,6 +26,22 @@ import re
26
26
  import stat
27
27
  import platform
28
28
 
29
+ # only for backup these scripts
30
+ def backup(
31
+ src="/Users/macjianfeng/Dropbox/github/python/py2ls/.venv/lib/python3.12/site-packages/py2ls/",
32
+ tar="/Users/macjianfeng/Dropbox/github/python/py2ls/py2ls/",
33
+ kind="py",
34
+ overwrite=True,
35
+ reverse=False,
36
+ verbose=False
37
+ ):
38
+ if reverse:
39
+ src, tar = tar,src
40
+ print(f"reversed")
41
+ f = listdir(src, kind, verbose=verbose)
42
+ [copy(i, tar, overwrite=overwrite, verbose=verbose) for i in f.path]
43
+ print(f"all files are copied from {os.path.basename(src)} to {tar}") if verbose else None
44
+
29
45
  def run_once_within(duration=60, reverse=False): # default 60s
30
46
  import time
31
47
 
@@ -2683,13 +2699,41 @@ def fload(fpath, kind=None, **kwargs):
2683
2699
  def load_excel(fpath, **kwargs):
2684
2700
  engine = kwargs.get("engine", "openpyxl")
2685
2701
  verbose = kwargs.pop("verbose", False)
2686
- if run_once_within(reverse=True):
2687
- use_pd("read_excel", verbose=verbose)
2688
- df = pd.read_excel(fpath, engine=engine, **kwargs)
2702
+ password=kwargs.pop("password",None)
2703
+
2704
+ if not password:
2705
+ if run_once_within(reverse=True):
2706
+ use_pd("read_excel", verbose=verbose)
2707
+ df = pd.read_excel(fpath, engine=engine, **kwargs)
2708
+ try:
2709
+ meta = pd.ExcelFile(fpath)
2710
+ print(f"n_sheet={len(meta.sheet_names)},\t'sheetname = 0 (default)':")
2711
+ [print(f"{i}:\t{i_}") for i, i_ in enumerate(meta.sheet_names)]
2712
+ except:
2713
+ pass
2714
+ return df
2715
+ #* needs a password?
2716
+ import msoffcrypto # pip install msoffcrypto-tool
2717
+ from io import BytesIO
2718
+
2719
+ # Open the encrypted Excel file
2720
+ with open(fpath, 'rb') as f:
2721
+ try:
2722
+ office_file = msoffcrypto.OfficeFile(f)
2723
+ office_file.load_key(password=password) # Provide the password
2724
+ decrypted = BytesIO()
2725
+ office_file.decrypt(decrypted)
2726
+ except:
2727
+ office_file = msoffcrypto.OfficeFile(f)
2728
+ office_file.load_key(password=depass(password)) # Provide the password
2729
+ decrypted = BytesIO()
2730
+ office_file.decrypt(decrypted)
2731
+ decrypted.seek(0)
2732
+ df = pd.read_excel(decrypted, engine=engine, **kwargs)
2689
2733
  try:
2690
- meata = pd.ExcelFile(fpath)
2691
- print(f"n_sheet={len(meata.sheet_names)},\t'sheetname = 0 (default)':")
2692
- [print(f"{i}:\t{i_}") for i, i_ in enumerate(meata.sheet_names)]
2734
+ meta = pd.ExcelFile(fpath)
2735
+ print(f"n_sheet={len(meta.sheet_names)},\t'sheetname = 0 (default)':")
2736
+ [print(f"{i}:\t{i_}") for i, i_ in enumerate(meta.sheet_names)]
2693
2737
  except:
2694
2738
  pass
2695
2739
  return df
@@ -3273,11 +3317,16 @@ def fsave(
3273
3317
  df = pd.DataFrame(data)
3274
3318
  df.to_csv(fpath, **kwargs_valid)
3275
3319
 
3276
- def save_xlsx(fpath, data, **kwargs):
3320
+
3321
+ def save_xlsx(fpath, data, password=None, **kwargs):
3322
+ import msoffcrypto
3323
+ from io import BytesIO
3277
3324
  verbose = kwargs.pop("verbose", False)
3278
3325
  sheet_name = kwargs.pop("sheet_name", "Sheet1")
3326
+
3279
3327
  if run_once_within(reverse=True):
3280
3328
  use_pd("to_excel", verbose=verbose)
3329
+
3281
3330
  if any(kwargs):
3282
3331
  format_excel(df=data, filename=fpath, **kwargs)
3283
3332
  else:
@@ -3302,16 +3351,30 @@ def fsave(
3302
3351
  kwargs.pop(key, None)
3303
3352
 
3304
3353
  df = pd.DataFrame(data)
3305
- # Check if the file exists, then append the sheet, otherwise create a new file
3306
- try:
3307
- # Use ExcelWriter with append mode if the file exists
3308
- with pd.ExcelWriter(
3309
- fpath, engine="openpyxl", mode="a", if_sheet_exists="new"
3310
- ) as writer:
3311
- df.to_excel(writer, sheet_name=sheet_name, index=False, **kwargs)
3312
- except FileNotFoundError:
3313
- # If file doesn't exist, create a new one
3314
- df.to_excel(fpath, sheet_name=sheet_name, index=False, **kwargs)
3354
+
3355
+ # Write to Excel without password first
3356
+ temp_file = BytesIO()
3357
+ df.to_excel(temp_file, sheet_name=sheet_name, index=False, engine="xlsxwriter", **kwargs)
3358
+
3359
+ # If a password is provided, encrypt the file
3360
+ if password:
3361
+ temp_file.seek(0)
3362
+ office_file = msoffcrypto.OfficeFile(temp_file)
3363
+ office_file.load_key(password=password) # Provide the password
3364
+
3365
+ # Encrypt and save the file
3366
+ with open(fpath, 'wb') as encrypted_file:
3367
+ office_file.encrypt(encrypted_file)
3368
+ else:
3369
+ # Save the file without encryption if no password is provided
3370
+ try:
3371
+ # Use ExcelWriter with append mode if the file exists
3372
+ with pd.ExcelWriter(fpath, engine="openpyxl", mode="a", if_sheet_exists="new") as writer:
3373
+ df.to_excel(writer, sheet_name=sheet_name, index=False, **kwargs)
3374
+ except FileNotFoundError:
3375
+ # If file doesn't exist, create a new one
3376
+ df.to_excel(fpath, sheet_name=sheet_name, index=False, **kwargs)
3377
+
3315
3378
 
3316
3379
  def save_ipynb(fpath, data, **kwargs):
3317
3380
  # Split the content by code fences to distinguish between code and markdown
@@ -4400,13 +4463,13 @@ def func_list(lib_name, opt="call"):
4400
4463
  return list_func(lib_name, opt=opt)
4401
4464
 
4402
4465
 
4403
- def copy(src, dst, overwrite=False):
4466
+ def copy(src, dst, overwrite=False, verbose=True):
4404
4467
  """Copy a file from src to dst."""
4405
4468
  try:
4406
4469
  dir_par_dst = os.path.dirname(dst)
4407
4470
  if not os.path.isdir(dir_par_dst):
4408
4471
  mkdir(dir_par_dst)
4409
- print(dir_par_dst)
4472
+ print(dir_par_dst) if verbose else None
4410
4473
  src = Path(src)
4411
4474
  dst = Path(dst)
4412
4475
  if not src.is_dir():
@@ -4421,7 +4484,7 @@ def copy(src, dst, overwrite=False):
4421
4484
  f"{dst.stem}_{datetime.now().strftime('_%H%M%S')}{dst.suffix}"
4422
4485
  )
4423
4486
  shutil.copy(src, dst)
4424
- print(f"\n Done! copy to {dst}\n")
4487
+ print(f"\n Done! copy to {dst}\n") if verbose else None
4425
4488
  else:
4426
4489
  dst = dst / src.name
4427
4490
  if dst.exists():
@@ -4432,7 +4495,7 @@ def copy(src, dst, overwrite=False):
4432
4495
  f"{dst.stem}_{datetime.now().strftime('%H%M%S')}"
4433
4496
  )
4434
4497
  shutil.copytree(src, dst)
4435
- print(f"\n Done! copy to {dst}\n")
4498
+ print(f"\n Done! copy to {dst}\n") if verbose else None
4436
4499
 
4437
4500
  except Exception as e:
4438
4501
  logging.error(f"Failed {e}")
@@ -4442,7 +4505,7 @@ def cut(src, dst, overwrite=False):
4442
4505
  return move(src=src, dst=dst, overwrite=overwrite)
4443
4506
 
4444
4507
 
4445
- def move(src, dst, overwrite=False):
4508
+ def move(src, dst, overwrite=False, verbose=True):
4446
4509
  try:
4447
4510
  dir_par_dst = os.path.dirname(dst)
4448
4511
  if not os.path.isdir(dir_par_dst):
@@ -4460,7 +4523,7 @@ def move(src, dst, overwrite=False):
4460
4523
  f"{dst.stem}_{datetime.now().strftime('_%H%M%S')}{dst.suffix}"
4461
4524
  )
4462
4525
  shutil.move(src, dst)
4463
- print(f"\n Done! moved to {dst}\n")
4526
+ print(f"\n Done! moved to {dst}\n") if verbose else None
4464
4527
  except Exception as e:
4465
4528
  logging.error(f"Failed to move file from {src} to {dst}: {e}")
4466
4529
 
@@ -4719,6 +4782,19 @@ def figsave(*args, dpi=300):
4719
4782
  plt.savefig(fname, format="emf", dpi=dpi, bbox_inches="tight", pad_inches=0)
4720
4783
  elif ftype.lower() == "fig":
4721
4784
  plt.savefig(fname, format="pdf", bbox_inches="tight", dpi=dpi, pad_inches=0)
4785
+
4786
+ elif ftype.lower() == "ico":
4787
+ # Ensure the image is in a format that can be saved as an icon (e.g., 32x32, 64x64, etc.)
4788
+ if img is None: # If no image is provided, use the matplotlib figure
4789
+ img = plt.figure()
4790
+ img.savefig(fname, dpi=dpi, format="png", bbox_inches="tight")
4791
+ img = Image.open(fname) # Load the saved figure image
4792
+
4793
+ # Resize the image to typical icon sizes and save it as .ico
4794
+ icon_sizes = [(32, 32), (64, 64), (128, 128), (256, 256)]
4795
+ img = img.convert("RGBA") # Ensure it has an alpha channel for transparency
4796
+ img.save(fname, format="ICO", sizes=icon_sizes)
4797
+ print(f"Icon saved @: {fname} with sizes: {icon_sizes}")
4722
4798
  print(f"\nSaved @: dpi={dpi}\n{fname}")
4723
4799
 
4724
4800
 
@@ -5497,7 +5573,6 @@ def detect_angle(image, by="median", template=None):
5497
5573
  print(f"Unknown method {by}: supported methods: {methods}")
5498
5574
  return 0
5499
5575
 
5500
-
5501
5576
  def imgsets(img,
5502
5577
  auto:bool=True,
5503
5578
  size=None,
@@ -5506,7 +5581,9 @@ def imgsets(img,
5506
5581
  show_axis:bool=False,
5507
5582
  plot_:bool=True,
5508
5583
  verbose:bool=False,
5509
- **kwargs):
5584
+ model:str="isnet-general-use",
5585
+ **kwargs,
5586
+ ):
5510
5587
  """
5511
5588
  Apply various enhancements and filters to an image using PIL's ImageEnhance and ImageFilter modules.
5512
5589
 
@@ -5562,6 +5639,26 @@ def imgsets(img,
5562
5639
  "BOX_BLUR",
5563
5640
  "MEDIAN_FILTER",
5564
5641
  ]
5642
+ # *Rembg is a tool to remove images background.
5643
+ # https://github.com/danielgatis/rembg
5644
+ rem_models = {
5645
+ "u2net": "general use cases.",
5646
+ "u2netp": "A lightweight version of u2net model.",
5647
+ "u2net_human_seg": "human segmentation.",
5648
+ "u2net_cloth_seg": "Cloths Parsing from human portrait. Here clothes are parsed into 3 category: Upper body, Lower body and Full body.",
5649
+ "silueta": "Same as u2net but the size is reduced to 43Mb.",
5650
+ "isnet-general-use": "A new pre-trained model for general use cases.",
5651
+ "isnet-anime": "A high-accuracy segmentation for anime character.",
5652
+ "sam": "any use cases.",
5653
+ "birefnet-general": "general use cases.",
5654
+ "birefnet-general-lite": "A light pre-trained model for general use cases.",
5655
+ "birefnet-portrait": "human portraits.",
5656
+ "birefnet-dis": "dichotomous image segmentation (DIS).",
5657
+ "birefnet-hrsod": "high-resolution salient object detection (HRSOD).",
5658
+ "birefnet-cod": "concealed object detection (COD).",
5659
+ "birefnet-massive": "A pre-trained model with massive dataset.",
5660
+ }
5661
+ models_support_rem=list(rem_models.keys())
5565
5662
  str_usage="""
5566
5663
  imgsets(dir_img, auto=1, color=1.5, plot_=0)
5567
5664
  imgsets(dir_img, color=2)
@@ -5569,6 +5666,7 @@ def imgsets(img,
5569
5666
  imgsets(dir_img, contrast=0, color=1.2, plot_=0)
5570
5667
  imgsets(get_clip(), flip="tb")# flip top and bottom
5571
5668
  imgsets(get_clip(), contrast=1, rm=[100, 5, 2]) #'foreground_threshold', 'background_threshold' and 'erode_structure_size'
5669
+ imgsets(dir_img, rm="birefnet-portrait") # with using custom model
5572
5670
  """
5573
5671
  if run_once_within():
5574
5672
  print(str_usage)
@@ -5577,28 +5675,7 @@ def imgsets(img,
5577
5675
  # adjust gama value
5578
5676
  inv_gamma = 1.0 / gamma
5579
5677
  lut = [int((i / float(v_max)) ** inv_gamma * int(v_max)) for i in range(int(v_max))]
5580
- return lut #image.point(lut)
5581
-
5582
- def confirm_rembg_models(model_name):
5583
- models_support = [
5584
- "u2net",
5585
- "u2netp",
5586
- "u2net_human_seg",
5587
- "u2net_cloth_seg",
5588
- "silueta",
5589
- "isnet-general-use",
5590
- "isnet-anime",
5591
- "sam",
5592
- ]
5593
- if model_name in models_support:
5594
- print(f"model_name: {model_name}")
5595
- return model_name
5596
- else:
5597
- print(
5598
- f"{model_name} cannot be found, check the name:{models_support}, default('isnet-general-use') has been used"
5599
- )
5600
- return "isnet-general-use"
5601
-
5678
+ return lut #image.point(lut)
5602
5679
  def auto_enhance(img):
5603
5680
  """
5604
5681
  Automatically enhances the image based on its characteristics, including brightness,
@@ -5701,7 +5778,7 @@ def imgsets(img,
5701
5778
  kwargs = {**auto_enhance(img_update), **kwargs}
5702
5779
  params=["sharp","color","contrast","bright","crop","rotate",'size',"resize",
5703
5780
  "thumbnail","cover","contain","filter","fit","pad",
5704
- "rem","rm","back","bg_color","cut",'gamma','flip']
5781
+ "rem","rm","back","bg_color","cut","gamma","flip","booster"]
5705
5782
  for k, value in kwargs.items():
5706
5783
  k = strcmp(k, params)[0] # correct the param name
5707
5784
  if "shar" in k.lower():
@@ -5722,7 +5799,7 @@ def imgsets(img,
5722
5799
  img_update = ImageOps.autocontrast(img_update)
5723
5800
  print("autocontrasted")
5724
5801
  except Exception as e:
5725
- print(f"Failed 'autocontrasted':{e}")
5802
+ print(f"Failed 'auto-contrasted':{e}")
5726
5803
  elif "bri" in k.lower():
5727
5804
  enhancer = ImageEnhance.Brightness(img_update)
5728
5805
  img_update = enhancer.enhance(value)
@@ -5765,9 +5842,14 @@ def imgsets(img,
5765
5842
  img_update = ImageOps.pad(img_update, size=value)
5766
5843
  elif "rem" in k.lower() or "rm" in k.lower() or "back" in k.lower():
5767
5844
  from rembg import remove, new_session
5768
-
5845
+ if verbose:
5846
+ preview(rem_models)
5847
+
5848
+ print(f"supported modles: {models_support_rem}")
5849
+ model=strcmp(model, models_support_rem)[0]
5850
+ session = new_session(model)
5769
5851
  if isinstance(value, bool):
5770
- session = new_session("isnet-general-use")
5852
+ print(f"using model:{model}")
5771
5853
  img_update = remove(img_update, session=session)
5772
5854
  elif value and isinstance(value, (int, float, list)):
5773
5855
  if verbose:
@@ -5779,14 +5861,14 @@ def imgsets(img,
5779
5861
  img_update = remove(
5780
5862
  img_update,
5781
5863
  alpha_matting=True,
5782
- alpha_matting_background_threshold=value,
5864
+ alpha_matting_background_threshold=value, session=session
5783
5865
  )
5784
5866
  elif 2 <= len(value) < 3:
5785
5867
  img_update = remove(
5786
5868
  img_update,
5787
5869
  alpha_matting=True,
5788
5870
  alpha_matting_background_threshold=value[0],
5789
- alpha_matting_foreground_threshold=value[1],
5871
+ alpha_matting_foreground_threshold=value[1], session=session
5790
5872
  )
5791
5873
  elif 3 <= len(value) < 4:
5792
5874
  img_update = remove(
@@ -5794,17 +5876,16 @@ def imgsets(img,
5794
5876
  alpha_matting=True,
5795
5877
  alpha_matting_background_threshold=value[0],
5796
5878
  alpha_matting_foreground_threshold=value[1],
5797
- alpha_matting_erode_size=value[2],
5879
+ alpha_matting_erode_size=value[2], session=session
5798
5880
  )
5799
5881
  elif isinstance(value, tuple): # replace the background color
5800
5882
  if len(value) == 3:
5801
5883
  value += (255,)
5802
- img_update = remove(img_update, bgcolor=value)
5884
+ img_update = remove(img_update, bgcolor=value, session=session)
5803
5885
  elif isinstance(value, str):
5804
- if confirm_rembg_models(value):
5805
- img_update = remove(img_update, session=new_session(value))
5806
- else:
5807
- img_update = remove(img_update)
5886
+ # use custom model
5887
+ print(f"using model:{strcmp(value, models_support_rem)[0]}")
5888
+ img_update = remove(img_update, session=new_session(strcmp(value, models_support_rem)[0]))
5808
5889
  elif "bg" in k.lower() and "color" in k.lower():
5809
5890
  from rembg import remove
5810
5891
 
@@ -5814,7 +5895,33 @@ def imgsets(img,
5814
5895
  if len(value) == 3:
5815
5896
  value += (255,)
5816
5897
  img_update = remove(img_update, bgcolor=value)
5817
-
5898
+ elif 'boost' in k.lower():
5899
+ import torch
5900
+ from realesrgan import RealESRGANer
5901
+ if verbose:
5902
+ print("Applying Real-ESRGAN for image reconstruction...")
5903
+ if isinstance(value, bool):
5904
+ scale=4
5905
+ elif isinstance(value, (float, int)):
5906
+ scale=value
5907
+ else:
5908
+ scale=4
5909
+
5910
+ # try:
5911
+ device = "cuda" if torch.cuda.is_available() else "cpu"
5912
+ dir_curr_script = os.path.dirname(os.path.abspath(__file__))
5913
+ model_path = dir_curr_script + "/data/RealESRGAN_x4plus.pth"
5914
+ model_RealESRGAN = RealESRGANer(device=device,
5915
+ scale=scale,
5916
+ model_path=model_path,
5917
+ model="RealESRGAN_x4plus"
5918
+ )
5919
+ # https://github.com/xinntao/Real-ESRGAN?tab=readme-ov-file#python-script
5920
+
5921
+ img_update = model_RealESRGAN.enhance(np.array(img_update))[0]
5922
+ # except Exception as e:
5923
+ # print(f"Failed to apply Real-ESRGAN: {e}")
5924
+
5818
5925
  # elif "ga" in k.lower() and "m" in k.lower():
5819
5926
  # img_update = gamma_correction(img_update, gamma=value)
5820
5927
  # Display the image if requested
@@ -10715,4 +10822,227 @@ def mouse(
10715
10822
  # "Image not found. Ensure the image is visible and parameters are correct."
10716
10823
  # )
10717
10824
  # except Exception as e:
10718
- # print(f"An error occurred: {e}")
10825
+ # print(f"An error occurred: {e}")
10826
+
10827
+
10828
+
10829
+ def py2installer(
10830
+ script_path: str=None,
10831
+ flatform:str="mingw64",
10832
+ output_dir: str = "dist",
10833
+ icon_path: str = None,
10834
+ extra_data: list = None,
10835
+ hidden_imports: list = None,
10836
+ plugins:list=None,
10837
+ use_nuitka: bool = True,
10838
+ onefile: bool = True,
10839
+ console: bool = True,
10840
+ clean_build: bool = False,
10841
+ additional_args: list = None,
10842
+ verbose: bool = True,
10843
+ use_docker: bool = False,
10844
+ docker_image: str = "python:3.12-slim",
10845
+ ):
10846
+ """
10847
+ to package Python scripts into standalone application.
10848
+
10849
+ script_path (str): Path to the Python script to package.
10850
+ output_dir (str): Directory where the executable will be stored.
10851
+ icon_path (str): Path to the .ico file for the executable icon.
10852
+ extra_data (list): List of additional data files or directories in "source:dest" format.
10853
+ hidden_imports (list): List of hidden imports to include.
10854
+ plugins (list): List of plugins imports to include.e.g., 'tk-inter'
10855
+ use_nuitka (bool): Whether to use Nuitka instead of PyInstaller.
10856
+ onefile (bool): If True, produces a single executable file.
10857
+ console (bool): If False, hides the console window (GUI mode).
10858
+ clean_build (bool): If True, cleans previous build and dist directories.
10859
+ additional_args (list): Additional arguments for PyInstaller/Nuitka.
10860
+ verbose (bool): If True, provides detailed logs.
10861
+ use_docker (bool): If True, uses Docker to package the script.
10862
+ docker_image (str): Docker image to use for packaging.
10863
+
10864
+ """
10865
+
10866
+ import os
10867
+ import sys
10868
+ import shutil
10869
+ import subprocess
10870
+ import sys
10871
+ import glob
10872
+ from pathlib import Path
10873
+ if run_once_within():
10874
+ usage_str="""
10875
+ # build locally
10876
+ py2installer(
10877
+ script_path="update_tab.py",
10878
+ output_dir="dist",
10879
+ icon_path="icon4app.ico",
10880
+ extra_data=["dat/*.xlsx:dat"],
10881
+ hidden_imports=["msoffcrypto", "tkinter", "pandas", "numpy"],
10882
+ onefile=True,
10883
+ console=False,
10884
+ clean_build=True,
10885
+ verbose=True,
10886
+ )
10887
+ # build via docker
10888
+ py2installer(
10889
+ "my_script.py",
10890
+ output_dir="dist",
10891
+ onefile=True,
10892
+ clean_build=True,
10893
+ use_docker=True,
10894
+ docker_image="python:3.12-slim"
10895
+ )
10896
+ """
10897
+ print(usage_str)
10898
+ if verbose:
10899
+ return
10900
+ else:
10901
+ pass
10902
+ # Check if the script path exists
10903
+ script_path = Path(script_path)
10904
+ if not script_path.exists():
10905
+ raise FileNotFoundError(f"Script '{script_path}' not found.")
10906
+
10907
+ # Clean build and dist directories if requested
10908
+ if clean_build:
10909
+ for folder in ["build", "dist"]:
10910
+ folder_path = Path(folder)
10911
+ if folder_path.exists():
10912
+ shutil.rmtree(folder_path, ignore_errors=True)
10913
+ # Recreate the folders
10914
+ for folder in ["build", "dist"]:
10915
+ folder_path = Path(folder)
10916
+ folder_path.mkdir(parents=True, exist_ok=True)
10917
+
10918
+
10919
+ if use_docker:
10920
+ # Ensure Docker is installed
10921
+ try:
10922
+ subprocess.run(["docker", "--version"], check=True, capture_output=True, text=True)
10923
+ except FileNotFoundError:
10924
+ raise EnvironmentError("Docker is not installed or not in the PATH.")
10925
+
10926
+ # Prepare Docker volume mappings
10927
+ script_dir = script_path.parent.resolve()
10928
+ dist_path = Path(output_dir).resolve()
10929
+ volumes = [
10930
+ f"{script_dir}:/app:rw",
10931
+ f"{dist_path}:/output:rw",
10932
+ ]
10933
+ docker_cmd = [
10934
+ "docker", "run", "--rm",
10935
+ "-v", volumes[0],
10936
+ "-v", volumes[1],
10937
+ docker_image,
10938
+ "bash", "-c",
10939
+ ]
10940
+
10941
+ # Build the packaging command inside the container
10942
+ cmd = ["nuitka"] if use_nuitka else ["pyinstaller"]
10943
+ if onefile:
10944
+ cmd.append("--onefile")
10945
+ if not console:
10946
+ cmd.append("--windowed")
10947
+ cmd.extend(["--distpath", "/output"])
10948
+ if icon_path:
10949
+ cmd.extend(["--icon", f"/app/{Path(icon_path).name}"])
10950
+ if extra_data:
10951
+ for data in extra_data:
10952
+ cmd.extend(["--add-data", f"/app/{data}"])
10953
+ if hidden_imports:
10954
+ for hidden in hidden_imports:
10955
+ cmd.extend(["--hidden-import", hidden])
10956
+ if additional_args:
10957
+ cmd.extend(additional_args)
10958
+ cmd.append(f"/app/{script_path.name}")
10959
+
10960
+ # Full command to execute inside the container
10961
+ docker_cmd.append(" ".join(cmd))
10962
+
10963
+ if verbose:
10964
+ print(f"Running Docker command: {' '.join(docker_cmd)}")
10965
+
10966
+ # Run Docker command
10967
+ try:
10968
+ subprocess.run(
10969
+ docker_cmd,
10970
+ capture_output=not verbose,
10971
+ text=True,
10972
+ check=True,
10973
+ )
10974
+ except subprocess.CalledProcessError as e:
10975
+ print(f"Error during Docker packaging:\n{e.stderr}", file=sys.stderr)
10976
+ raise
10977
+ else:
10978
+ # Handle local packaging (native build)
10979
+ cmd = ["nuitka"]
10980
+ cmd.append("--standalone") # Make sure to use --standalone for independent environments
10981
+ if 'min' in flatform.lower():
10982
+ cmd.append("--mingw64")
10983
+ if onefile:
10984
+ cmd.append("--onefile")
10985
+ if not console:
10986
+ # cmd.append("--windows-disable-console") # Disabled based on your request
10987
+ pass
10988
+
10989
+ cmd.extend([f"--output-dir={output_dir}"]) # Correct the space issue here
10990
+ if icon_path:
10991
+ icon_path = Path(icon_path)
10992
+ if not icon_path.exists():
10993
+ raise FileNotFoundError(f"Icon file '{icon_path}' not found.")
10994
+ cmd.extend([f"--windows-icon-from-ico={icon_path}"])
10995
+
10996
+ if extra_data:
10997
+ for data in extra_data:
10998
+ if "*" in data:
10999
+ matches = glob.glob(data.split(":")[0])
11000
+ for match in matches:
11001
+ dest = data.split(":")[1]
11002
+ cmd.extend(
11003
+ [
11004
+ "--include-data-file=" if use_nuitka else "--add-data",
11005
+ f"{match}:{dest}",
11006
+ ]
11007
+ )
11008
+ else:
11009
+ cmd.extend(
11010
+ ["--include-data-file=" if use_nuitka else "--add-data", data]
11011
+ )
11012
+
11013
+ if hidden_imports:
11014
+ cmd.extend([f"--nofollow-import-to={','.join(hidden_imports)}"])
11015
+
11016
+ if plugins:
11017
+ for plugin in plugins:
11018
+ cmd.extend([f"--plugin-enable={plugin}"])
11019
+
11020
+ if additional_args:
11021
+ cmd.extend(additional_args)
11022
+
11023
+ # Add the script path (final positional argument)
11024
+ cmd.append(str(script_path))
11025
+
11026
+ # Ensure Windows shell compatibility
11027
+ shell_flag = sys.platform.startswith("win")
11028
+
11029
+ # Run the command
11030
+ if verbose:
11031
+ print(f"Running command: {' '.join(cmd)}")
11032
+ try:
11033
+ result = subprocess.run(
11034
+ cmd,
11035
+ capture_output=not verbose,
11036
+ text=True,
11037
+ shell=shell_flag,
11038
+ check=True,
11039
+ )
11040
+ if verbose:
11041
+ print(result.stdout)
11042
+ except subprocess.CalledProcessError as e:
11043
+ print(f"Error during packaging:\n{e.stderr}", file=sys.stderr)
11044
+ print(" ".join(cmd))
11045
+ raise
11046
+
11047
+ print("\nPackaging complete. Check the output directory for the executable.")
11048
+