py2ls 0.2.5.8__tar.gz → 0.2.5.9__tar.gz

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.
Files changed (259) hide show
  1. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/PKG-INFO +1 -1
  2. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/ips.py +336 -86
  3. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/pyproject.toml +1 -1
  4. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/README.md +0 -0
  5. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.DS_Store +0 -0
  6. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/.DS_Store +0 -0
  7. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/COMMIT_EDITMSG +0 -0
  8. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/FETCH_HEAD +0 -0
  9. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/HEAD +0 -0
  10. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/config +0 -0
  11. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/description +0 -0
  12. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/hooks/applypatch-msg.sample +0 -0
  13. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/hooks/commit-msg.sample +0 -0
  14. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/hooks/fsmonitor-watchman.sample +0 -0
  15. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/hooks/post-update.sample +0 -0
  16. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/hooks/pre-applypatch.sample +0 -0
  17. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/hooks/pre-commit.sample +0 -0
  18. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/hooks/pre-merge-commit.sample +0 -0
  19. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/hooks/pre-push.sample +0 -0
  20. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/hooks/pre-rebase.sample +0 -0
  21. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/hooks/pre-receive.sample +0 -0
  22. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/hooks/prepare-commit-msg.sample +0 -0
  23. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/hooks/push-to-checkout.sample +0 -0
  24. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/hooks/update.sample +0 -0
  25. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/index +0 -0
  26. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/info/exclude +0 -0
  27. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/logs/HEAD +0 -0
  28. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/logs/refs/heads/main +0 -0
  29. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/logs/refs/remotes/origin/HEAD +0 -0
  30. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/logs/refs/remotes/origin/main +0 -0
  31. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/.DS_Store +0 -0
  32. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/01/d5bd8065e6860c0bd23ff9fa57161806a099e1 +0 -0
  33. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/09/08da26de58c114225ad81f484b80bf5d351b34 +0 -0
  34. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/0b/409e1bc918277010f5679b402d1d1dda53e15c +0 -0
  35. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/12/c2808a1b3a4d0892a4154dfba1e2ae3770fa73 +0 -0
  36. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/14/449a0e6ba4ea2f1a73acf63ef91c9c6193f9ed +0 -0
  37. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/15/a8e468aacfcb440e090020f36d0b985d45da23 +0 -0
  38. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/1a/b4585881a6a42889f01aa0cfe25fd5acfaf46f +0 -0
  39. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/1c/3f92adda34344bcbbbf9d409c79855ae2aaea8 +0 -0
  40. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/1c/9314c5f69b9390068a2a8616875d974849d71f +0 -0
  41. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/1d/fe9d9633b24ea560354f4f93d39c6e5f163ea0 +0 -0
  42. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/20/72c28e83f4347959d29f7b3a6c1fc3e4ee6b59 +0 -0
  43. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/24/6b368b986f758630c46dc02b7fa512b53422f7 +0 -0
  44. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/25/b796accd261b9135fd32a2c00785f68edf6c46 +0 -0
  45. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/27/aa6074f652bc6f7078f8647489d9ee8e24f0e2 +0 -0
  46. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/28/c2969d785c1b892c2a96b3f00eba63a59811b3 +0 -0
  47. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/2a/ae95d517d213b660bf4f65a4e0cfae7bb893eb +0 -0
  48. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/2a/fdf45791a26d42ccead35ace76a8f0b2a56561 +0 -0
  49. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/30/a2f8da47ee947811dc8d993f5a06a45de374f4 +0 -0
  50. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/32/fd627b62fad7cf3b2f9e34ab9777126a0987ad +0 -0
  51. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/34/9e31b6a3634cea102ce5588b98c11cc1738605 +0 -0
  52. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/34/b6f3a2ee84f39bed4eee57f2c0e0afb994feb1 +0 -0
  53. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/35/1a5f491ab97eee9d1ee699478d75a8bb5d3dc2 +0 -0
  54. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/36/b4a1b7403abc6c360f8fe2cb656ab945254971 +0 -0
  55. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/36/e56a361f526eafa59c5235a5c990bf288b5f9c +0 -0
  56. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/36/ef43e50009e59db11812c258846d9e38718173 +0 -0
  57. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/39/7ead045fbbcfb17c62019eb18fe21ed05dbee5 +0 -0
  58. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/39/b13be65125556784e44c7a1d9821703c7ab67e +0 -0
  59. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/3b/507acc7f23391644cc0b824b1e79fd2677a362 +0 -0
  60. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/3b/bd972aa7ad680858f8dfbd0f7fcd97756f0d6f +0 -0
  61. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/3c/bbe5f4173d165127b9ad96119f1ec24c306ffc +0 -0
  62. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/3d/9d10d27724657a436c65a6254bfd213d4b3562 +0 -0
  63. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/3f/d6561300938afbb3d11976cf9c8f29549280d9 +0 -0
  64. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/41/dcf4b3bf0460946b2da93776cf9e836d62178f +0 -0
  65. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/43/dbd49b2ee367c5434dd545e3b5795434f2ef0b +0 -0
  66. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/45/b1b6178bacbfc997811a998b5cc60c1ea7fac8 +0 -0
  67. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/47/6cbd5a7c5e35cddef2f8a38bdc4896d403b095 +0 -0
  68. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/48/a88fc5806305d0bb0755ee6801161b79696972 +0 -0
  69. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/4f/7afb40dff2153d857fc85748c2eecb85125042 +0 -0
  70. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/50/08ddfcf53c02e82d7eee2e57c38e5672ef89f6 +0 -0
  71. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/53/e0deb1cb4c2c606bced6e7f9a66b0fda60980d +0 -0
  72. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/56/e4e8b2d5545e0256090f45aa8fc42c5fe067d0 +0 -0
  73. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/57/63d0c52f5c9c69e89d514a1f96034947abe21a +0 -0
  74. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/57/bd1c0199483ab316235b094543b85edec6c35e +0 -0
  75. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/58/20a729045d4dc7e37ccaf8aa8eec126850afe2 +0 -0
  76. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/59/380c4c26bdcd4d9b71ae3e2e35f05b3f26c5ab +0 -0
  77. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/5a/192565abf89c9d765af846ce6d53a92b1ce7ad +0 -0
  78. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/60/f273eb1c412d916fa3f11318a7da7a9911b52a +0 -0
  79. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/61/570cec8c061abe74121f27f5face6c69b98f99 +0 -0
  80. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/62/4488173ed2c8936fa5cea3cf5dd3f26a30b86e +0 -0
  81. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/62/7c81b23b4e56e87b042b650b0103653cc9e34a +0 -0
  82. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/62/d90ccf8cbefdc2e4fd475e7c6f4f76e9fdf801 +0 -0
  83. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/63/100154b27846e8010e55b6bf4b3d7762c14c5f +0 -0
  84. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/64/27a4edff08f93d98f511418423f09f2ab90bcd +0 -0
  85. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/66/6227eeeba24073e63811e89f1449f3d958f183 +0 -0
  86. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/66/c998778721d424bd0aae80602dabbffa93af2e +0 -0
  87. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/68/6df3072c8b025fb18106ed2df505994ad062a9 +0 -0
  88. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/69/13c452ca319f7cbf6a0836dc10a5bb033c84e4 +0 -0
  89. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/6a/52e747a2b349b128d1490d9e896d2323818eb7 +0 -0
  90. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/6b/7fde264d93a7a0986d394c46c7650d0ce2ab92 +0 -0
  91. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/6c/cebb29b7f3f5b0c889f6dadbf9ff066554587d +0 -0
  92. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/6d/c2cdf4a84e538e5d4777486aeff87e42f41799 +0 -0
  93. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/6d/ee29dbdcc84edeeacede105110446f3ccac963 +0 -0
  94. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/71/36b2074a2754be8b58127d82250e5b37e3c373 +0 -0
  95. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/72/245a05b0966011cb381e6b32b0465000e969ab +0 -0
  96. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/72/e4179337639859678ddaecf38b16f33aaec8e1 +0 -0
  97. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/78/063f4c863fc371ec0313303c0a81283b35d9b6 +0 -0
  98. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/78/3d4167bc95c9d2175e0df03ef1c1c880ba75ab +0 -0
  99. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/79/7ae089b2212a937840e215276005ce76881307 +0 -0
  100. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/7e/5956c806b5edc344d46dab599dec337891ba1f +0 -0
  101. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/81/8f26b7bf042269729020cf944fc362d66ba27e +0 -0
  102. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/82/70b319ce4046854fbe7dc41054b6c2d112dab2 +0 -0
  103. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/84/59071b722a255b774a80b27746033f8141ab39 +0 -0
  104. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/85/aee46f478e9afdb84d50a05242c53b04ed2e21 +0 -0
  105. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/86/e288b46f8fe179907e4413f665aeb5053fddb1 +0 -0
  106. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/87/ef1fc3f7f1ddc4d0ab9b3e65381ce9f3388621 +0 -0
  107. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/8b/84f56978e1de8f2ae82abce5f8b3e182d365cd +0 -0
  108. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/8e/55a7d2b96184030211f20c9b9af201eefcac82 +0 -0
  109. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/91/c69ad88fe0ba94aa7859fb5f7edac5e6f1a3f7 +0 -0
  110. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/94/74152b4b463d70ae5ad07f0c658be3e296026b +0 -0
  111. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/94/f7dbe88e80c4205a901b71eb8f181974376bba +0 -0
  112. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/97/1aef09ea939f46b60b9646f8d524c78a9220f4 +0 -0
  113. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/9b/ec5ee2236ee2d5532c36bfd132e23c58fdb69c +0 -0
  114. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/9d/0df52899fe95279059286d9c0ec42287edc168 +0 -0
  115. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/a1/5389729850729fc7bd78a54f26fce77f30be12 +0 -0
  116. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/a1/906da89d1174f74867800c74c43af36253bd5e +0 -0
  117. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/a4/63fdd23e5efd713db8a71f316f3a1c7bd60916 +0 -0
  118. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/a5/ec8f74642fbba27f7ea78c53b372ae0c7dedce +0 -0
  119. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/a7/3e13eafee65c5b8d73ad2d3ea46d0eee82f0d3 +0 -0
  120. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/b0/56be4be89ba6b76949dd641df45bb7036050c8 +0 -0
  121. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/b0/9cd7856d58590578ee1a4f3ad45d1310a97f87 +0 -0
  122. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/b2/18e6a0f0f1c4df8cdefa9852058348abc713b7 +0 -0
  123. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/b3/4f7f271c6d6105e35a6556ffda71d03afe8c96 +0 -0
  124. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/b3/69579064bde9de9a19d114fc33e4e48cc8c0e4 +0 -0
  125. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/b5/61831c7dce8ea51e7ee6b6fa35745f14d8242d +0 -0
  126. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/b7/2c9e75ab7d0afe594664650aa8f6c772f5ac64 +0 -0
  127. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/bb/81ccc0513f18fc160b54a82861e9a80d23f4f6 +0 -0
  128. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/bb/934eb33bc1a8b85630bf680caffd99560c1b8f +0 -0
  129. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/bf/67907e337021ebff434e02b19b30a741c144af +0 -0
  130. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/bf/b54d65922ce1dfda1aaa014913a54e7172d0bc +0 -0
  131. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/c1/20fc812b9ad311c34a3608512d6a9d976bb48e +0 -0
  132. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/c1/397c6ed72c4e20ef6b9ab83163e9a6baba5b45 +0 -0
  133. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/c4/cba65f1163661999ee4b8ed23342b63bc1300c +0 -0
  134. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/c6/7f17e5707313600efcb85e9a3fedea35dba591 +0 -0
  135. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/c6/f32aced880bd165a251cb52b26b0c1107e2141 +0 -0
  136. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/cc/45df1d317a2eb63ff1ff3a5f3b4a9f98fd92b5 +0 -0
  137. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/cd/822b3574a88ebdd1ed82fd6983f37e626d52b4 +0 -0
  138. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/cf/0c0d9c6fb09473aaeb7f7e2edbd770c3f2ef3d +0 -0
  139. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/d2/992df305f4b56a466a2f221aeb182ddd20f418 +0 -0
  140. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/d6/39e8af592cd75a318d8affddd1bcc70c2095f2 +0 -0
  141. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/d6/9ab1c4aadf279936dd778e8346ba60f74705b6 +0 -0
  142. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/d8/4688b54c0040a30976b3a6540bc47adf7ce680 +0 -0
  143. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/d9/005f2cc7fc4e65f14ed5518276007c08cf2fd0 +0 -0
  144. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/d9/c2403fd166ce791b4e9d0c6792ed8342c71fcd +0 -0
  145. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/d9/dfa5aee51e92a541b707e8e7baea6f06deff98 +0 -0
  146. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/db/141dbaa93594df2a8156182f361ee4db829359 +0 -0
  147. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/db/3f2cd643292057936230b95cf7ec3046affe11 +0 -0
  148. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/db/ffa8ea7bda721d0cee7b9e4ce5b2ef927733ff +0 -0
  149. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/dc/c2bdbafb3296e09d9ee4955cfa55d275825f94 +0 -0
  150. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/dc/cdbd4266765d840be2ae35ab1752a0fa312c16 +0 -0
  151. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/dd/87fb5f606fe380d81e6fe3a2c98f9f99e3e09b +0 -0
  152. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/de/214c626ac2dd2685bfaa0bc0fc20f528d014d7 +0 -0
  153. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/df/e0770424b2a19faf507a501ebfc23be8f54e7b +0 -0
  154. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/e2/f2f8f4c25e62a297fc55f36acc6b01cfbab76f +0 -0
  155. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/e3/1356f90ea6dd0577b5e0b40b206319adcbf085 +0 -0
  156. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/e3/5a4dafc50850cacac7bf76c56db2715cbda2c4 +0 -0
  157. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/e4/6c715352db9fe3c887a635f1916df4ca1f4ff9 +0 -0
  158. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/e5/0580a0bd1e1b3d29f834382b80fceb61d5cf0c +0 -0
  159. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/e9/391ffe371f1cc43b42ef09b705d9c767c2e14f +0 -0
  160. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/ea/3a18cc75e53792744ef754e05d3f4481768c13 +0 -0
  161. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/ec/40fd8bf8e4c342534a9fc020289e402ba6bc9d +0 -0
  162. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/ec/d980279432b13f0374b90ca439a6329cdece0f +0 -0
  163. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/ee/cee64eacaff022dcdc509c0c2b1da492f21060 +0 -0
  164. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/f1/e50757fddc28b445545dc7e2759b54cdd0f42e +0 -0
  165. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/f4/b64d3107b39e3ad6f540c6607004ea34e6c024 +0 -0
  166. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/f4/ba7f815b886797b73fede071d86e0c134d2bc7 +0 -0
  167. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/f5/61c3c1bf1c9ea9c9d1f556a7be2869f71f3bdf +0 -0
  168. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/f6/44a8ff56fa035105fc517cbb1ac46c3d8e349a +0 -0
  169. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/f7/c98ba5c2f903e603b1f5e63d49fbc8a43815cc +0 -0
  170. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/f9/045a08e96eb76848fc4d68e3e3e687cca39a2d +0 -0
  171. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/fa/147e6bb78a2e8db241d231295fd7f1ed061af8 +0 -0
  172. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/objects/fc/292e793ecfd42240ac43be407023bd731fa9e7 +0 -0
  173. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/refs/.DS_Store +0 -0
  174. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/refs/heads/main +0 -0
  175. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/refs/remotes/origin/HEAD +0 -0
  176. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.git/refs/remotes/origin/main +0 -0
  177. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.gitattributes +0 -0
  178. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/.gitignore +0 -0
  179. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/LICENSE +0 -0
  180. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/README.md +0 -0
  181. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/__init__.py +0 -0
  182. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/batman.py +0 -0
  183. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/bio.py +0 -0
  184. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/brain_atlas.py +0 -0
  185. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/chat.py +0 -0
  186. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/corr.py +0 -0
  187. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/correlators.py +0 -0
  188. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/.DS_Store +0 -0
  189. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/db2ls_sql_chtsht.json +0 -0
  190. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/docs_links.json +0 -0
  191. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/email/email_html_template.html +0 -0
  192. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/hyper_param_autogluon_zeroshot2024.json +0 -0
  193. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/hyper_param_tabrepo_2024.py +0 -0
  194. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/lang_code_iso639.json +0 -0
  195. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/mygenes_fields_241022.txt +0 -0
  196. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/sns_info.json +0 -0
  197. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/.DS_Store +0 -0
  198. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/example/.DS_Store +0 -0
  199. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/example/style1.pdf +0 -0
  200. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/example/style2.pdf +0 -0
  201. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/example/style3.pdf +0 -0
  202. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/example/style4.pdf +0 -0
  203. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/example/style5.pdf +0 -0
  204. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/example/style6.pdf +0 -0
  205. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/example/style7.pdf +0 -0
  206. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/example/style8.pdf +0 -0
  207. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/example/style9.pdf +0 -0
  208. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/style1.json +0 -0
  209. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/style10.json +0 -0
  210. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/style11.json +0 -0
  211. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/style12.json +0 -0
  212. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/style2.json +0 -0
  213. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/style3.json +0 -0
  214. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/style4.json +0 -0
  215. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/style5.json +0 -0
  216. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/style6.json +0 -0
  217. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/style7.json +0 -0
  218. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/style8.json +0 -0
  219. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/style9.json +0 -0
  220. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/.DS_Store +0 -0
  221. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/grid.mplstyle +0 -0
  222. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/high-contrast.mplstyle +0 -0
  223. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/high-vis.mplstyle +0 -0
  224. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/ieee.mplstyle +0 -0
  225. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/light.mplstyl +0 -0
  226. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/muted.mplstyle +0 -0
  227. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/nature-reviews-latex.mplstyle +0 -0
  228. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/nature-reviews.mplstyle +0 -0
  229. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/nature.mplstyle +0 -0
  230. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/no-latex.mplstyle +0 -0
  231. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/notebook.mplstyle +0 -0
  232. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/paper.mplstyle +0 -0
  233. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/retro.mplstyle +0 -0
  234. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/sans.mplstyle +0 -0
  235. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/scatter.mplstyle +0 -0
  236. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/science.mplstyle +0 -0
  237. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/std-colors.mplstyle +0 -0
  238. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/vibrant.mplstyle +0 -0
  239. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/tiles.csv +0 -0
  240. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/usages_pd.json +0 -0
  241. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/data/usages_sns.json +0 -0
  242. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/db2ls.py +0 -0
  243. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/doc.py +0 -0
  244. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/ec2ls.py +0 -0
  245. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/export_requirements.py +0 -0
  246. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/fetch_update.py +0 -0
  247. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/freqanalysis.py +0 -0
  248. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/ich2ls.py +0 -0
  249. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/ml2ls.py +0 -0
  250. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/mol.py +0 -0
  251. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/netfinder.py +0 -0
  252. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/nl2ls.py +0 -0
  253. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/ocr.py +0 -0
  254. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/plot.py +0 -0
  255. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/setuptools-70.1.0-py3-none-any.whl +0 -0
  256. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/sleep_events_detectors.py +0 -0
  257. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/stats.py +0 -0
  258. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/translator.py +0 -0
  259. {py2ls-0.2.5.8 → py2ls-0.2.5.9}/py2ls/wb_detector.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: py2ls
3
- Version: 0.2.5.8
3
+ Version: 0.2.5.9
4
4
  Summary: py(thon)2(too)ls
5
5
  Author: Jianfeng
6
6
  Author-email: Jianfeng.Liu0413@gmail.com
@@ -3,7 +3,7 @@ import pandas as pd
3
3
  import sys
4
4
  import os
5
5
  from IPython.display import display
6
- from typing import List, Optional, Union,Any
6
+ from typing import Dict,List, Optional, Union,Any
7
7
 
8
8
  from regex import X
9
9
 
@@ -5245,63 +5245,169 @@ def split_path(fpath):
5245
5245
  dir_ch = "".join(fpath.split(f_slash)[-1:])
5246
5246
  return dir_par, dir_ch
5247
5247
 
5248
+ from pathlib import Path
5249
+ import matplotlib.pyplot as plt
5250
+ from PIL import Image
5251
+ import numpy as np
5252
+ import cv2
5248
5253
 
5249
- def figsave(*args, dpi=300):
5250
- import matplotlib.pyplot as plt
5251
- from PIL import Image
5254
+ def figsave(*args, dpi=300, **kwargs):
5255
+ bbox_inches = kwargs.pop("bbox_inches", "tight")
5256
+ pad_inches = kwargs.pop("pad_inches", 0)
5257
+ facecolor = kwargs.pop("facecolor", "white")
5258
+ edgecolor = kwargs.pop("edgecolor", "auto")
5252
5259
 
5253
5260
  dir_save = None
5254
5261
  fname = None
5255
5262
  img = None
5256
- f_slash = "/" if "mac" in get_os().lower() else "\\"
5263
+
5257
5264
  for arg in args:
5258
5265
  if isinstance(arg, str):
5259
- if f_slash in arg:
5260
- dir_save = arg
5266
+ path = Path(arg)
5267
+ if path.suffix: # Has file extension
5268
+ fname = path.name
5269
+ dir_save = path.parent
5261
5270
  else:
5262
- fname = arg
5271
+ dir_save = path
5263
5272
  elif isinstance(arg, (Image.Image, np.ndarray)):
5264
- img = arg # Store the PIL image if provided
5273
+ img = arg # Store PIL image or numpy array
5265
5274
 
5266
- if dir_save is None:
5267
- dir_save = "./"
5275
+ # Set default save directory
5276
+ dir_save = Path(dir_save) if dir_save else Path(".")
5277
+ dir_save.mkdir(parents=True, exist_ok=True)
5278
+
5279
+ # Handle filename and extension
5280
+ if fname is None:
5281
+ fname = "figure"
5282
+ fname = dir_save / fname
5283
+ if fname.suffix == "":
5284
+ fname = fname.with_suffix(".pdf") # Default format
5285
+
5286
+ ftype = fname.suffix.lstrip(".").lower()
5287
+
5288
+ # Save figure based on file type
5289
+ if ftype == "eps":
5290
+ plt.savefig(fname, format="eps", bbox_inches=bbox_inches)
5291
+ plt.savefig(fname.with_suffix(".pdf"), format="pdf", dpi=dpi,
5292
+ pad_inches=pad_inches, bbox_inches=bbox_inches,
5293
+ facecolor=facecolor, edgecolor=edgecolor)
5294
+ elif ftype == "pdf":
5295
+ plt.savefig(fname, format="pdf", dpi=dpi, pad_inches=pad_inches,
5296
+ bbox_inches=bbox_inches, facecolor=facecolor, edgecolor=edgecolor)
5297
+ elif ftype in ["jpg", "jpeg", "png", "tiff", "tif"]:
5298
+ if img is not None: # If an image is provided
5299
+ if isinstance(img, Image.Image):
5300
+ img = img.convert("RGB") if img.mode == "RGBA" else img
5301
+ img.save(fname, format=ftype.upper(), dpi=(dpi, dpi))
5302
+ elif isinstance(img, np.ndarray):
5303
+ if img.ndim == 2:
5304
+ Image.fromarray(img).save(fname, format=ftype.upper(), dpi=(dpi, dpi))
5305
+ elif img.ndim == 3:
5306
+ if img.shape[2] == 3:
5307
+ img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
5308
+ elif img.shape[2] == 4:
5309
+ img = cv2.cvtColor(img, cv2.COLOR_BGRA2RGBA)
5310
+ Image.fromarray(img).save(fname, format=ftype.upper(), dpi=(dpi, dpi))
5311
+ else:
5312
+ raise ValueError("Unexpected image dimensions.")
5313
+ else:
5314
+ plt.savefig(fname, format=ftype, dpi=dpi, pad_inches=pad_inches,
5315
+ bbox_inches=bbox_inches, facecolor=facecolor, edgecolor=edgecolor)
5316
+ elif ftype == "ico":
5317
+ if img is None:
5318
+ plt.savefig(fname, dpi=dpi, pad_inches=pad_inches,
5319
+ bbox_inches=bbox_inches, facecolor=facecolor, edgecolor=edgecolor)
5320
+ img = Image.open(fname)
5321
+ img = img.convert("RGBA")
5322
+ icon_sizes = [(32, 32), (64, 64), (128, 128), (256, 256)]
5323
+ img.save(fname, format="ICO", sizes=icon_sizes)
5324
+ print(f"Icon saved @: {fname} with sizes: {icon_sizes}")
5325
+ else:
5326
+ raise ValueError(f"Unsupported file format: {ftype}")
5327
+
5328
+ print(f"\nSaved @ {fname} (dpi={dpi})")
5329
+
5330
+ def figsave(*args, dpi=300, **kwargs):
5331
+ """
5332
+ Save a Matplotlib figure or image file in various formats.
5333
+
5334
+ This function automatically determines whether to save a Matplotlib figure
5335
+ or an image (PIL or NumPy array) and handles different file formats, including:
5336
+ - PDF, EPS, PNG, JPG, TIFF, ICO, EMF
5337
+
5338
+ Parameters:
5339
+ -----------
5340
+ *args : str, PIL.Image, np.ndarray
5341
+ - File path (directory and/or filename) to save the figure.
5342
+ - If an image is provided (PIL or NumPy), it will be saved accordingly.
5343
+
5344
+ dpi : int, optional (default=300)
5345
+ - Resolution (dots per inch) for saved figures.
5346
+
5347
+ **kwargs : dict
5348
+ - Additional keyword arguments for `matplotlib.pyplot.savefig()`, including:
5349
+ - bbox_inches (str, default="tight"): Bounding box for figure.
5350
+ - pad_inches (float, default=0): Padding around figure.
5351
+ - facecolor (str, default="white"): Background color.
5352
+ - edgecolor (str, default="auto"): Edge color.
5353
+
5354
+ Supported Formats:
5355
+ ------------------
5356
+ - Vector: `pdf`, `eps`, `emf`
5357
+ - Raster: `png`, `jpg`, `jpeg`, `tiff`, `tif`, `ico`
5358
+
5359
+ Example Usage:
5360
+ --------------
5361
+ >>> figsave("output_plot.pdf")
5362
+ >>> figsave("figs/plot.png", dpi=600)
5363
+ >>> figsave("./results/figure", format="pdf")
5364
+ >>> figsave("icons/logo.ico", image) # Save an image file as an icon
5268
5365
 
5269
- # dir_save=dir_save+f_slash if not dir_save.endswith(f_slash) else dir_save
5270
- dir_par = f_slash.join(dir_save.split(f_slash)[:-1])
5271
- dir_ch = "".join(dir_save.split(f_slash)[-1:])
5272
- if not dir_par.endswith(f_slash):
5273
- dir_par += f_slash
5366
+ Returns:
5367
+ --------
5368
+ None
5369
+ """
5370
+ import matplotlib.pyplot as plt
5371
+ from PIL import Image
5372
+ from pathlib import Path
5373
+
5374
+ bbox_inches=kwargs.pop("bbox_inches","tight")
5375
+ pad_inches=kwargs.pop("pad_inches",0)
5376
+ facecolor=kwargs.pop("facecolor",'white')
5377
+ edgecolor=kwargs.pop("edgecolor",'auto')
5378
+
5379
+ dir_save = None
5380
+ fname = None
5381
+ img = None
5382
+ for arg in args:
5383
+ if isinstance(arg, str):
5384
+ path = Path(arg)
5385
+ if path.suffix: # Has file extension
5386
+ fname = path.name
5387
+ dir_save = path.parent
5388
+ else:
5389
+ dir_save = path
5390
+ elif isinstance(arg, (Image.Image, np.ndarray)):
5391
+ img = arg # Store PIL image or numpy array
5274
5392
 
5393
+ dir_save = Path(dir_save) if dir_save else Path(".")
5394
+ dir_save.mkdir(parents=True, exist_ok=True)
5395
+ # Handle filename and extension
5275
5396
  if fname is None:
5276
- fname = dir_ch
5277
- mkdir(dir_par)
5278
- ftype = fname.split(".")[-1]
5279
- if len(fname.split(".")) == 1:
5280
- ftype = "nofmt"
5281
- fname = dir_par + fname + "." + ftype
5397
+ fname = dir_save
5282
5398
  else:
5283
- fname = dir_par + fname
5399
+ fname = dir_save / fname
5400
+ if fname.suffix == "":
5401
+ fname = fname.with_suffix(".pdf") # Default format
5402
+
5403
+ ftype = fname.suffix.lstrip(".").lower()
5284
5404
 
5285
5405
  # Save figure based on file type
5286
- if ftype.lower() == "eps":
5287
- plt.savefig(fname, format="eps", bbox_inches="tight")
5288
- plt.savefig(
5289
- fname.replace(".eps", ".pdf"),
5290
- format="pdf",
5291
- bbox_inches="tight",
5292
- dpi=dpi,
5293
- pad_inches=0,
5294
- )
5295
- elif ftype.lower() == "nofmt": # default: both "tif" and "pdf"
5296
- fname_corr = fname.replace("nofmt", "pdf")
5297
- plt.savefig(
5298
- fname_corr, format="pdf", bbox_inches="tight", dpi=dpi, pad_inches=0
5299
- )
5300
- fname = fname.replace("nofmt", "tif")
5301
- plt.savefig(fname, format="tiff", dpi=dpi, bbox_inches="tight", pad_inches=0)
5302
- print(f"default saving filetype: both 'tif' and 'pdf")
5303
- elif ftype.lower() == "pdf":
5304
- plt.savefig(fname, format="pdf", bbox_inches="tight", dpi=dpi, pad_inches=0)
5406
+ if ftype == "eps":
5407
+ plt.savefig(fname, format="eps", bbox_inches=bbox_inches)
5408
+ plt.savefig(fname.with_suffix(".pdf"), format="pdf", dpi=dpi,
5409
+ pad_inches=pad_inches, bbox_inches=bbox_inches,
5410
+ facecolor=facecolor, edgecolor=edgecolor)
5305
5411
  elif ftype.lower() in ["jpg", "jpeg", "png", "tiff", "tif"]:
5306
5412
  if img is not None: # If a PIL image is provided
5307
5413
  if isinstance(img, Image.Image):
@@ -5310,63 +5416,46 @@ def figsave(*args, dpi=300):
5310
5416
  img.save(fname, format=ftype.upper(), dpi=(dpi, dpi))
5311
5417
  elif isinstance(img, np.ndarray):
5312
5418
  import cv2
5313
-
5314
- # Check the shape of the image to determine color mode
5315
5419
  if img.ndim == 2:
5316
5420
  # Grayscale image
5317
- Image.fromarray(img).save(
5318
- fname, format=ftype.upper(), dpi=(dpi, dpi)
5319
- )
5421
+ Image.fromarray(img).save(fname, format=ftype.upper(), dpi=(dpi, dpi))
5320
5422
  elif img.ndim == 3:
5321
5423
  if img.shape[2] == 3:
5322
5424
  # RGB image
5323
5425
  img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
5324
- Image.fromarray(img).save(
5325
- fname, format=ftype.upper(), dpi=(dpi, dpi)
5326
- )
5426
+ Image.fromarray(img).save(fname, format=ftype.upper(), dpi=(dpi, dpi))
5327
5427
  elif img.shape[2] == 4:
5328
5428
  # RGBA image
5329
- img = cv2.cvtColor(
5330
- img, cv2.COLOR_BGRA2RGBA
5331
- ) # Convert BGRA to RGBA
5332
- Image.fromarray(img).save(
5333
- fname, format=ftype.upper(), dpi=(dpi, dpi)
5334
- )
5429
+ img = cv2.cvtColor(img, cv2.COLOR_BGRA2RGBA) # Convert BGRA to RGBA
5430
+ Image.fromarray(img).save(fname, format=ftype.upper(), dpi=(dpi, dpi))
5335
5431
  else:
5336
- raise ValueError(
5337
- "Unexpected number of channels in the image array."
5338
- )
5432
+ raise ValueError("Unexpected number of channels in the image array.")
5339
5433
  else:
5340
- raise ValueError(
5341
- "Image array has an unexpected number of dimensions."
5342
- )
5434
+ raise ValueError("Image array has an unexpected number of dimensions.")
5343
5435
  else:
5344
- plt.savefig(
5345
- fname,
5346
- format=ftype.lower(),
5347
- dpi=dpi,
5348
- bbox_inches="tight",
5349
- transparent=True,
5350
- pad_inches=0,
5351
- )
5352
- elif ftype.lower() == "emf":
5353
- plt.savefig(fname, format="emf", dpi=dpi, bbox_inches="tight", pad_inches=0)
5354
- elif ftype.lower() == "fig":
5355
- plt.savefig(fname, format="pdf", bbox_inches="tight", dpi=dpi, pad_inches=0)
5356
-
5436
+ plt.savefig(fname,format=ftype.lower(),dpi=dpi,pad_inches=pad_inches,bbox_inches=bbox_inches,facecolor=facecolor,edgecolor=edgecolor)
5437
+ elif ftype.lower() in ["emf","pdf","fig"]:
5438
+ plt.savefig(fname,format=ftype.lower(),dpi=dpi,pad_inches=pad_inches,bbox_inches=bbox_inches,facecolor=facecolor,edgecolor=edgecolor)
5357
5439
  elif ftype.lower() == "ico":
5358
5440
  # Ensure the image is in a format that can be saved as an icon (e.g., 32x32, 64x64, etc.)
5359
5441
  if img is None: # If no image is provided, use the matplotlib figure
5360
- img = plt.figure()
5361
- img.savefig(fname, dpi=dpi, format="png", bbox_inches="tight")
5442
+ img = plt.figure()
5443
+ print(fname)
5444
+ img.savefig(fname,
5445
+ format="png",
5446
+ dpi=dpi,
5447
+ pad_inches=pad_inches,
5448
+ bbox_inches=bbox_inches,
5449
+ facecolor=facecolor,
5450
+ edgecolor=edgecolor )
5362
5451
  img = Image.open(fname) # Load the saved figure image
5363
5452
 
5364
5453
  # Resize the image to typical icon sizes and save it as .ico
5365
5454
  icon_sizes = [(32, 32), (64, 64), (128, 128), (256, 256)]
5366
- img = img.convert("RGBA") # Ensure it has an alpha channel for transparency
5455
+ img = img.convert("RGBA")
5367
5456
  img.save(fname, format="ICO", sizes=icon_sizes)
5368
5457
  print(f"Icon saved @: {fname} with sizes: {icon_sizes}")
5369
- print(f"\nSaved @: dpi={dpi}\n{fname}")
5458
+ print(f"\n✅ Saved @: dpi={dpi}\n{fname}")
5370
5459
 
5371
5460
 
5372
5461
  def is_str_color(s):
@@ -8022,21 +8111,20 @@ def format_excel(
8022
8111
  pil_img=img_path = None
8023
8112
  if isinstance(img_data, dict):
8024
8113
  if "path" in img_data:
8025
- img_path = img_data["path"] # File path
8026
- img_ = drawing.image.Image(img_path)
8114
+ img_ = drawing.image.Image(img_data["path"])# File path
8027
8115
  elif "image" in img_data:
8028
- pil_img = img_data["image"] # PIL Image object
8116
+ img_ = drawing.image.Image(img_data["image"])# PIL Image object
8029
8117
  elif "array" in img_data:
8030
- pil_img = Image.fromarray(img_data["array"]) # Convert NumPy array to PIL Image
8118
+ img_ = drawing.image.Image(Image.fromarray(img_data["array"]))# Convert NumPy array to PIL Image
8031
8119
 
8032
8120
  img_width = img_data.get("width", None)
8033
8121
  img_height = img_data.get("height", None)
8034
8122
  elif isinstance(img_data, str):
8035
- img_path = img_data # Direct file path
8123
+ img_ = drawing.image.Image(img_data)# Direct file path
8036
8124
  elif isinstance(img_data, (PIL.Image.Image,PIL.PngImagePlugin.PngImageFile)):
8037
- pil_img = img_data # Direct PIL Image object
8125
+ img_ = drawing.image.Image(img_data)# Direct PIL Image object
8038
8126
  elif isinstance(img_data, np.ndarray):
8039
- pil_img = Image.fromarray(img_data) # Convert NumPy array to PIL Image
8127
+ img_ = drawing.image.Image(Image.fromarray(img_data))# Convert NumPy array to PIL Image
8040
8128
  elif pil_img:
8041
8129
  img_ = drawing.image.Image(pil_img)
8042
8130
 
@@ -8230,7 +8318,89 @@ def _df_outlier(
8230
8318
 
8231
8319
  return processed_data
8232
8320
 
8321
+ def df_group(
8322
+ data: pd.DataFrame,
8323
+ columns: Union[str, list, None] = None,
8324
+ by: str = None,
8325
+ param: Dict[str, Any] = None,
8326
+ sep: Union[str, list] = [", ",","],
8327
+ dropna: bool = True,
8328
+ unique: bool = False,
8329
+ astype: type = str,
8330
+ merge: List[str] = None,
8331
+ merge_symbo_column:str=' & ',
8332
+ merge_symbo_cell:str='[]',# ["{}","()","[]"]
8333
+ ) -> pd.DataFrame:
8334
+ """
8335
+ Groups a dataframe based on a specified column and applies aggregation functions dynamically.
8336
+
8337
+ Parameters:
8338
+ data (pd.DataFrame): The dataframe to be grouped.
8339
+ columns (Union[str, list, None]): Columns to select; if None, all columns are selected.
8340
+ by (str): The column name to group by.
8341
+ param (dict): A dictionary specifying aggregation rules.
8342
+ sep (Union[str, list]): Separator for concatenated values. when sep is a list, then sep[0] used for general, sep[1] used in the merging
8343
+ dropna (bool): Whether to drop NaN values before aggregation.
8344
+ unique (bool): Whether to apply uniqueness before concatenation.
8345
+ astype (type): Data type to cast values before aggregation.
8346
+ merge (List[str]): List of columns to merge into a single paired column.
8347
+ merge_symbo_column:str: indicate in the columns, default ("&")
8348
+ merge_symbo_cell:str=default: '{}' or can select from ["{}","()","[]"]
8349
+
8350
+ Usage:
8351
+ data = pd.DataFrame({
8352
+ "Cage Tag": [1, 1, 2, 2, 3],
8353
+ "Physical Tag": ["A1", "A2", "B1", "B2", "C1"],
8354
+ "Sex": ["M", "F", "M", "M", "F"],
8355
+ "Date of Birth": ["2021-06-01", "2021-06-02", "2021-07-01", "2021-07-02", "2021-08-01"],
8356
+ "Age": [34, 35, 30, 31, 29],
8357
+ "State": ["Mating", "Resting", "Mating", "Resting", "Mating"],
8358
+ "Owner": ["Dr. Smith", "Dr. Smith", "Dr. Brown", "Dr. Brown", "Dr. Lee"],
8359
+ })
8360
+ display(data)
8361
+ result = df_group(data,
8362
+ # columns=["Sex", "Date of Birth", "Age", "State"],
8363
+ by="Cage Tag",
8364
+ merge=["Age", "State"],
8365
+ merge_symbo_column="|",
8366
+ # astype=str
8367
+ # sep=[',', '_'],
8368
+ merge_symbo_cell=None
8369
+ )
8370
+ result
8371
+
8372
+
8373
+ """
8374
+ if param is None:
8375
+ param = {}
8376
+ if columns is None:
8377
+ columns = data.columns.tolist()
8378
+ elif isinstance(columns, str):
8379
+ columns = [columns]
8380
+ if not isinstance(sep, list):
8381
+ sep = [sep]
8382
+ sep.extend(sep) if len(sep)==1 else None
8233
8383
 
8384
+ # Merge specified columns into a single column
8385
+ if merge:
8386
+ merge_col_name = merge_symbo_column.join(merge)
8387
+ # data[merge_col_name] = data[merge].apply(lambda row: tuple(map(astype, row.dropna() if dropna else row)), axis=1)
8388
+ if merge_symbo_cell is None:
8389
+ data[merge_col_name] = data[merge].apply(lambda row: f"{sep[1].join(map(astype, row.dropna()))}" if dropna else f"{sep[1].join(map(astype, row))}", axis=1)
8390
+ elif len(merge_symbo_cell)==2:
8391
+ data[merge_col_name] = data[merge].apply(lambda row: f"{merge_symbo_cell[0]}{sep[1].join(map(astype, row.dropna()))}{merge_symbo_cell[1]}" if dropna else f"{merge_symbo_cell[0]}{sep[1].join(map(astype, row))}{merge_symbo_cell[1]}", axis=1)
8392
+ else:
8393
+ data[merge_col_name] = data[merge].apply(lambda row: f"[{sep[1].join(map(astype, row.dropna()))}]" if dropna else f"[{sep[1].join(map(astype, row))}]", axis=1)
8394
+ columns.append(merge_col_name)
8395
+
8396
+ default_aggregations = {
8397
+ col: (lambda x: sep[0].join(map(astype, x.dropna().unique() if unique else x.dropna())) if dropna else sep[0].join(map(astype, x.unique() if unique else x)))
8398
+ for col in columns if col != by and (merge is None or col not in merge)
8399
+ }
8400
+ aggregation_rules = {**default_aggregations, **param}
8401
+
8402
+ grouped_df = data.groupby(by).agg(aggregation_rules).reset_index()
8403
+ return grouped_df
8234
8404
  def df_outlier(
8235
8405
  data,
8236
8406
  columns=None,
@@ -12520,3 +12690,83 @@ def py2installer(
12520
12690
  raise
12521
12691
 
12522
12692
  print("\nPackaging complete. Check the output directory for the executable.")
12693
+
12694
+
12695
+ def set_theme(
12696
+ context="paper",
12697
+ style="whitegrid",
12698
+ palette="deep",
12699
+ font="sans-serif",
12700
+ font_scale=1.0,
12701
+ color_codes=True,
12702
+ grid_alpha=0.5,
12703
+ grid_linewidth=0.8,
12704
+ grid_linestyle="--",
12705
+ tick_direction="out",
12706
+ # tick_length=4,
12707
+ spine_visibility=False,
12708
+ # figsize=(8, 6),
12709
+ # linewidth=2,
12710
+ dpi=100,
12711
+ rc=None,
12712
+ ):
12713
+ """
12714
+ to configure Seaborn theme with maximum flexibility.
12715
+
12716
+ # Example Usage
12717
+ set_sns_theme(font_scale=1.2, grid_alpha=0.8, tick_direction="in", dpi=150)
12718
+
12719
+ Parameters:
12720
+ - context: Plotting context ('notebook', 'paper', 'talk', 'poster')
12721
+ - style: Style of the plot ('darkgrid', 'whitegrid', 'dark', 'white', 'ticks')
12722
+ - palette: Color palette (string or list of colors)
12723
+ - font: Font family ('sans-serif', 'serif', etc.)
12724
+ - font_scale: Scaling factor for fonts
12725
+ - color_codes: Boolean, whether to use seaborn color codes
12726
+ - grid_alpha: Opacity of the grid lines
12727
+ - grid_linewidth: Thickness of grid lines
12728
+ - grid_linestyle: Style of grid lines ('-', '--', '-.', ':')
12729
+ - tick_direction: Direction of ticks ('in', 'out', 'inout')
12730
+ - tick_length: Length of ticks
12731
+ - spine_visibility: Whether to show plot spines (True/False)
12732
+ - figsize: Default figure size as tuple (width, height)
12733
+ - linewidth: Default line width for plots
12734
+ - dpi: Resolution of the figure
12735
+ - rc: Dictionary of additional rc settings
12736
+ """
12737
+ import seaborn as sns
12738
+ import matplotlib.pyplot as plt
12739
+
12740
+ # Define additional rc parameters for fine-tuning
12741
+ rc_params = {
12742
+ # "axes.grid": True,
12743
+ "grid.alpha": grid_alpha,
12744
+ "grid.linewidth": grid_linewidth,
12745
+ "grid.linestyle": grid_linestyle,
12746
+ "xtick.direction": tick_direction,
12747
+ "ytick.direction": tick_direction,
12748
+ # "xtick.major.size": tick_length,
12749
+ # "ytick.major.size": tick_length,
12750
+ # "axes.linewidth": linewidth,
12751
+ # "figure.figsize": figsize,
12752
+ "figure.dpi": dpi,
12753
+ "axes.spines.top": spine_visibility,
12754
+ "axes.spines.right": spine_visibility,
12755
+ "axes.spines.bottom": spine_visibility,
12756
+ "axes.spines.left": spine_visibility,
12757
+ }
12758
+
12759
+ # Merge user-provided rc settings
12760
+ if rc:
12761
+ rc_params.update(rc)
12762
+
12763
+ # Apply the theme settings
12764
+ sns.set_theme(
12765
+ context=context,
12766
+ style=style,
12767
+ palette=palette,
12768
+ font=font,
12769
+ font_scale=font_scale,
12770
+ color_codes=color_codes,
12771
+ rc=rc_params,
12772
+ )
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "py2ls"
3
- version = "0.2.5.8"
3
+ version = "0.2.5.9"
4
4
  description = "py(thon)2(too)ls"
5
5
  authors = ["Jianfeng <Jianfeng.Liu0413@gmail.com>"]
6
6
  readme = "README.md"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes