py2ls 0.2.5.7__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.7 → py2ls-0.2.5.9}/PKG-INFO +1 -1
  2. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/ips.py +390 -126
  3. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/pyproject.toml +1 -1
  4. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/README.md +0 -0
  5. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.DS_Store +0 -0
  6. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/.DS_Store +0 -0
  7. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/COMMIT_EDITMSG +0 -0
  8. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/FETCH_HEAD +0 -0
  9. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/HEAD +0 -0
  10. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/config +0 -0
  11. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/description +0 -0
  12. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/hooks/applypatch-msg.sample +0 -0
  13. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/hooks/commit-msg.sample +0 -0
  14. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/hooks/fsmonitor-watchman.sample +0 -0
  15. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/hooks/post-update.sample +0 -0
  16. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/hooks/pre-applypatch.sample +0 -0
  17. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/hooks/pre-commit.sample +0 -0
  18. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/hooks/pre-merge-commit.sample +0 -0
  19. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/hooks/pre-push.sample +0 -0
  20. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/hooks/pre-rebase.sample +0 -0
  21. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/hooks/pre-receive.sample +0 -0
  22. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/hooks/prepare-commit-msg.sample +0 -0
  23. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/hooks/push-to-checkout.sample +0 -0
  24. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/hooks/update.sample +0 -0
  25. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/index +0 -0
  26. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/info/exclude +0 -0
  27. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/logs/HEAD +0 -0
  28. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/logs/refs/heads/main +0 -0
  29. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/logs/refs/remotes/origin/HEAD +0 -0
  30. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/logs/refs/remotes/origin/main +0 -0
  31. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/.DS_Store +0 -0
  32. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/01/d5bd8065e6860c0bd23ff9fa57161806a099e1 +0 -0
  33. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/09/08da26de58c114225ad81f484b80bf5d351b34 +0 -0
  34. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/0b/409e1bc918277010f5679b402d1d1dda53e15c +0 -0
  35. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/12/c2808a1b3a4d0892a4154dfba1e2ae3770fa73 +0 -0
  36. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/14/449a0e6ba4ea2f1a73acf63ef91c9c6193f9ed +0 -0
  37. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/15/a8e468aacfcb440e090020f36d0b985d45da23 +0 -0
  38. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/1a/b4585881a6a42889f01aa0cfe25fd5acfaf46f +0 -0
  39. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/1c/3f92adda34344bcbbbf9d409c79855ae2aaea8 +0 -0
  40. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/1c/9314c5f69b9390068a2a8616875d974849d71f +0 -0
  41. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/1d/fe9d9633b24ea560354f4f93d39c6e5f163ea0 +0 -0
  42. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/20/72c28e83f4347959d29f7b3a6c1fc3e4ee6b59 +0 -0
  43. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/24/6b368b986f758630c46dc02b7fa512b53422f7 +0 -0
  44. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/25/b796accd261b9135fd32a2c00785f68edf6c46 +0 -0
  45. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/27/aa6074f652bc6f7078f8647489d9ee8e24f0e2 +0 -0
  46. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/28/c2969d785c1b892c2a96b3f00eba63a59811b3 +0 -0
  47. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/2a/ae95d517d213b660bf4f65a4e0cfae7bb893eb +0 -0
  48. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/2a/fdf45791a26d42ccead35ace76a8f0b2a56561 +0 -0
  49. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/30/a2f8da47ee947811dc8d993f5a06a45de374f4 +0 -0
  50. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/32/fd627b62fad7cf3b2f9e34ab9777126a0987ad +0 -0
  51. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/34/9e31b6a3634cea102ce5588b98c11cc1738605 +0 -0
  52. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/34/b6f3a2ee84f39bed4eee57f2c0e0afb994feb1 +0 -0
  53. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/35/1a5f491ab97eee9d1ee699478d75a8bb5d3dc2 +0 -0
  54. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/36/b4a1b7403abc6c360f8fe2cb656ab945254971 +0 -0
  55. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/36/e56a361f526eafa59c5235a5c990bf288b5f9c +0 -0
  56. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/36/ef43e50009e59db11812c258846d9e38718173 +0 -0
  57. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/39/7ead045fbbcfb17c62019eb18fe21ed05dbee5 +0 -0
  58. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/39/b13be65125556784e44c7a1d9821703c7ab67e +0 -0
  59. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/3b/507acc7f23391644cc0b824b1e79fd2677a362 +0 -0
  60. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/3b/bd972aa7ad680858f8dfbd0f7fcd97756f0d6f +0 -0
  61. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/3c/bbe5f4173d165127b9ad96119f1ec24c306ffc +0 -0
  62. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/3d/9d10d27724657a436c65a6254bfd213d4b3562 +0 -0
  63. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/3f/d6561300938afbb3d11976cf9c8f29549280d9 +0 -0
  64. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/41/dcf4b3bf0460946b2da93776cf9e836d62178f +0 -0
  65. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/43/dbd49b2ee367c5434dd545e3b5795434f2ef0b +0 -0
  66. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/45/b1b6178bacbfc997811a998b5cc60c1ea7fac8 +0 -0
  67. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/47/6cbd5a7c5e35cddef2f8a38bdc4896d403b095 +0 -0
  68. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/48/a88fc5806305d0bb0755ee6801161b79696972 +0 -0
  69. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/4f/7afb40dff2153d857fc85748c2eecb85125042 +0 -0
  70. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/50/08ddfcf53c02e82d7eee2e57c38e5672ef89f6 +0 -0
  71. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/53/e0deb1cb4c2c606bced6e7f9a66b0fda60980d +0 -0
  72. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/56/e4e8b2d5545e0256090f45aa8fc42c5fe067d0 +0 -0
  73. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/57/63d0c52f5c9c69e89d514a1f96034947abe21a +0 -0
  74. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/57/bd1c0199483ab316235b094543b85edec6c35e +0 -0
  75. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/58/20a729045d4dc7e37ccaf8aa8eec126850afe2 +0 -0
  76. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/59/380c4c26bdcd4d9b71ae3e2e35f05b3f26c5ab +0 -0
  77. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/5a/192565abf89c9d765af846ce6d53a92b1ce7ad +0 -0
  78. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/60/f273eb1c412d916fa3f11318a7da7a9911b52a +0 -0
  79. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/61/570cec8c061abe74121f27f5face6c69b98f99 +0 -0
  80. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/62/4488173ed2c8936fa5cea3cf5dd3f26a30b86e +0 -0
  81. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/62/7c81b23b4e56e87b042b650b0103653cc9e34a +0 -0
  82. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/62/d90ccf8cbefdc2e4fd475e7c6f4f76e9fdf801 +0 -0
  83. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/63/100154b27846e8010e55b6bf4b3d7762c14c5f +0 -0
  84. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/64/27a4edff08f93d98f511418423f09f2ab90bcd +0 -0
  85. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/66/6227eeeba24073e63811e89f1449f3d958f183 +0 -0
  86. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/66/c998778721d424bd0aae80602dabbffa93af2e +0 -0
  87. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/68/6df3072c8b025fb18106ed2df505994ad062a9 +0 -0
  88. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/69/13c452ca319f7cbf6a0836dc10a5bb033c84e4 +0 -0
  89. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/6a/52e747a2b349b128d1490d9e896d2323818eb7 +0 -0
  90. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/6b/7fde264d93a7a0986d394c46c7650d0ce2ab92 +0 -0
  91. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/6c/cebb29b7f3f5b0c889f6dadbf9ff066554587d +0 -0
  92. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/6d/c2cdf4a84e538e5d4777486aeff87e42f41799 +0 -0
  93. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/6d/ee29dbdcc84edeeacede105110446f3ccac963 +0 -0
  94. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/71/36b2074a2754be8b58127d82250e5b37e3c373 +0 -0
  95. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/72/245a05b0966011cb381e6b32b0465000e969ab +0 -0
  96. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/72/e4179337639859678ddaecf38b16f33aaec8e1 +0 -0
  97. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/78/063f4c863fc371ec0313303c0a81283b35d9b6 +0 -0
  98. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/78/3d4167bc95c9d2175e0df03ef1c1c880ba75ab +0 -0
  99. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/79/7ae089b2212a937840e215276005ce76881307 +0 -0
  100. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/7e/5956c806b5edc344d46dab599dec337891ba1f +0 -0
  101. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/81/8f26b7bf042269729020cf944fc362d66ba27e +0 -0
  102. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/82/70b319ce4046854fbe7dc41054b6c2d112dab2 +0 -0
  103. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/84/59071b722a255b774a80b27746033f8141ab39 +0 -0
  104. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/85/aee46f478e9afdb84d50a05242c53b04ed2e21 +0 -0
  105. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/86/e288b46f8fe179907e4413f665aeb5053fddb1 +0 -0
  106. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/87/ef1fc3f7f1ddc4d0ab9b3e65381ce9f3388621 +0 -0
  107. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/8b/84f56978e1de8f2ae82abce5f8b3e182d365cd +0 -0
  108. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/8e/55a7d2b96184030211f20c9b9af201eefcac82 +0 -0
  109. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/91/c69ad88fe0ba94aa7859fb5f7edac5e6f1a3f7 +0 -0
  110. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/94/74152b4b463d70ae5ad07f0c658be3e296026b +0 -0
  111. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/94/f7dbe88e80c4205a901b71eb8f181974376bba +0 -0
  112. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/97/1aef09ea939f46b60b9646f8d524c78a9220f4 +0 -0
  113. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/9b/ec5ee2236ee2d5532c36bfd132e23c58fdb69c +0 -0
  114. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/9d/0df52899fe95279059286d9c0ec42287edc168 +0 -0
  115. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/a1/5389729850729fc7bd78a54f26fce77f30be12 +0 -0
  116. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/a1/906da89d1174f74867800c74c43af36253bd5e +0 -0
  117. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/a4/63fdd23e5efd713db8a71f316f3a1c7bd60916 +0 -0
  118. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/a5/ec8f74642fbba27f7ea78c53b372ae0c7dedce +0 -0
  119. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/a7/3e13eafee65c5b8d73ad2d3ea46d0eee82f0d3 +0 -0
  120. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/b0/56be4be89ba6b76949dd641df45bb7036050c8 +0 -0
  121. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/b0/9cd7856d58590578ee1a4f3ad45d1310a97f87 +0 -0
  122. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/b2/18e6a0f0f1c4df8cdefa9852058348abc713b7 +0 -0
  123. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/b3/4f7f271c6d6105e35a6556ffda71d03afe8c96 +0 -0
  124. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/b3/69579064bde9de9a19d114fc33e4e48cc8c0e4 +0 -0
  125. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/b5/61831c7dce8ea51e7ee6b6fa35745f14d8242d +0 -0
  126. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/b7/2c9e75ab7d0afe594664650aa8f6c772f5ac64 +0 -0
  127. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/bb/81ccc0513f18fc160b54a82861e9a80d23f4f6 +0 -0
  128. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/bb/934eb33bc1a8b85630bf680caffd99560c1b8f +0 -0
  129. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/bf/67907e337021ebff434e02b19b30a741c144af +0 -0
  130. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/bf/b54d65922ce1dfda1aaa014913a54e7172d0bc +0 -0
  131. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/c1/20fc812b9ad311c34a3608512d6a9d976bb48e +0 -0
  132. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/c1/397c6ed72c4e20ef6b9ab83163e9a6baba5b45 +0 -0
  133. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/c4/cba65f1163661999ee4b8ed23342b63bc1300c +0 -0
  134. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/c6/7f17e5707313600efcb85e9a3fedea35dba591 +0 -0
  135. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/c6/f32aced880bd165a251cb52b26b0c1107e2141 +0 -0
  136. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/cc/45df1d317a2eb63ff1ff3a5f3b4a9f98fd92b5 +0 -0
  137. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/cd/822b3574a88ebdd1ed82fd6983f37e626d52b4 +0 -0
  138. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/cf/0c0d9c6fb09473aaeb7f7e2edbd770c3f2ef3d +0 -0
  139. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/d2/992df305f4b56a466a2f221aeb182ddd20f418 +0 -0
  140. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/d6/39e8af592cd75a318d8affddd1bcc70c2095f2 +0 -0
  141. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/d6/9ab1c4aadf279936dd778e8346ba60f74705b6 +0 -0
  142. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/d8/4688b54c0040a30976b3a6540bc47adf7ce680 +0 -0
  143. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/d9/005f2cc7fc4e65f14ed5518276007c08cf2fd0 +0 -0
  144. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/d9/c2403fd166ce791b4e9d0c6792ed8342c71fcd +0 -0
  145. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/d9/dfa5aee51e92a541b707e8e7baea6f06deff98 +0 -0
  146. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/db/141dbaa93594df2a8156182f361ee4db829359 +0 -0
  147. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/db/3f2cd643292057936230b95cf7ec3046affe11 +0 -0
  148. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/db/ffa8ea7bda721d0cee7b9e4ce5b2ef927733ff +0 -0
  149. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/dc/c2bdbafb3296e09d9ee4955cfa55d275825f94 +0 -0
  150. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/dc/cdbd4266765d840be2ae35ab1752a0fa312c16 +0 -0
  151. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/dd/87fb5f606fe380d81e6fe3a2c98f9f99e3e09b +0 -0
  152. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/de/214c626ac2dd2685bfaa0bc0fc20f528d014d7 +0 -0
  153. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/df/e0770424b2a19faf507a501ebfc23be8f54e7b +0 -0
  154. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/e2/f2f8f4c25e62a297fc55f36acc6b01cfbab76f +0 -0
  155. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/e3/1356f90ea6dd0577b5e0b40b206319adcbf085 +0 -0
  156. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/e3/5a4dafc50850cacac7bf76c56db2715cbda2c4 +0 -0
  157. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/e4/6c715352db9fe3c887a635f1916df4ca1f4ff9 +0 -0
  158. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/e5/0580a0bd1e1b3d29f834382b80fceb61d5cf0c +0 -0
  159. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/e9/391ffe371f1cc43b42ef09b705d9c767c2e14f +0 -0
  160. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/ea/3a18cc75e53792744ef754e05d3f4481768c13 +0 -0
  161. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/ec/40fd8bf8e4c342534a9fc020289e402ba6bc9d +0 -0
  162. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/ec/d980279432b13f0374b90ca439a6329cdece0f +0 -0
  163. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/ee/cee64eacaff022dcdc509c0c2b1da492f21060 +0 -0
  164. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/f1/e50757fddc28b445545dc7e2759b54cdd0f42e +0 -0
  165. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/f4/b64d3107b39e3ad6f540c6607004ea34e6c024 +0 -0
  166. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/f4/ba7f815b886797b73fede071d86e0c134d2bc7 +0 -0
  167. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/f5/61c3c1bf1c9ea9c9d1f556a7be2869f71f3bdf +0 -0
  168. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/f6/44a8ff56fa035105fc517cbb1ac46c3d8e349a +0 -0
  169. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/f7/c98ba5c2f903e603b1f5e63d49fbc8a43815cc +0 -0
  170. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/f9/045a08e96eb76848fc4d68e3e3e687cca39a2d +0 -0
  171. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/fa/147e6bb78a2e8db241d231295fd7f1ed061af8 +0 -0
  172. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/objects/fc/292e793ecfd42240ac43be407023bd731fa9e7 +0 -0
  173. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/refs/.DS_Store +0 -0
  174. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/refs/heads/main +0 -0
  175. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/refs/remotes/origin/HEAD +0 -0
  176. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.git/refs/remotes/origin/main +0 -0
  177. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.gitattributes +0 -0
  178. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/.gitignore +0 -0
  179. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/LICENSE +0 -0
  180. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/README.md +0 -0
  181. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/__init__.py +0 -0
  182. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/batman.py +0 -0
  183. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/bio.py +0 -0
  184. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/brain_atlas.py +0 -0
  185. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/chat.py +0 -0
  186. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/corr.py +0 -0
  187. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/correlators.py +0 -0
  188. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/.DS_Store +0 -0
  189. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/db2ls_sql_chtsht.json +0 -0
  190. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/docs_links.json +0 -0
  191. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/email/email_html_template.html +0 -0
  192. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/hyper_param_autogluon_zeroshot2024.json +0 -0
  193. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/hyper_param_tabrepo_2024.py +0 -0
  194. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/lang_code_iso639.json +0 -0
  195. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/mygenes_fields_241022.txt +0 -0
  196. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/sns_info.json +0 -0
  197. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/.DS_Store +0 -0
  198. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/example/.DS_Store +0 -0
  199. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/example/style1.pdf +0 -0
  200. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/example/style2.pdf +0 -0
  201. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/example/style3.pdf +0 -0
  202. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/example/style4.pdf +0 -0
  203. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/example/style5.pdf +0 -0
  204. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/example/style6.pdf +0 -0
  205. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/example/style7.pdf +0 -0
  206. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/example/style8.pdf +0 -0
  207. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/example/style9.pdf +0 -0
  208. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/style1.json +0 -0
  209. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/style10.json +0 -0
  210. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/style11.json +0 -0
  211. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/style12.json +0 -0
  212. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/style2.json +0 -0
  213. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/style3.json +0 -0
  214. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/style4.json +0 -0
  215. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/style5.json +0 -0
  216. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/style6.json +0 -0
  217. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/style7.json +0 -0
  218. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/style8.json +0 -0
  219. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/style9.json +0 -0
  220. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/.DS_Store +0 -0
  221. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/grid.mplstyle +0 -0
  222. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/high-contrast.mplstyle +0 -0
  223. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/high-vis.mplstyle +0 -0
  224. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/ieee.mplstyle +0 -0
  225. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/light.mplstyl +0 -0
  226. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/muted.mplstyle +0 -0
  227. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/nature-reviews-latex.mplstyle +0 -0
  228. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/nature-reviews.mplstyle +0 -0
  229. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/nature.mplstyle +0 -0
  230. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/no-latex.mplstyle +0 -0
  231. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/notebook.mplstyle +0 -0
  232. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/paper.mplstyle +0 -0
  233. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/retro.mplstyle +0 -0
  234. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/sans.mplstyle +0 -0
  235. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/scatter.mplstyle +0 -0
  236. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/science.mplstyle +0 -0
  237. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/std-colors.mplstyle +0 -0
  238. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/styles/stylelib/vibrant.mplstyle +0 -0
  239. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/tiles.csv +0 -0
  240. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/usages_pd.json +0 -0
  241. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/data/usages_sns.json +0 -0
  242. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/db2ls.py +0 -0
  243. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/doc.py +0 -0
  244. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/ec2ls.py +0 -0
  245. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/export_requirements.py +0 -0
  246. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/fetch_update.py +0 -0
  247. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/freqanalysis.py +0 -0
  248. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/ich2ls.py +0 -0
  249. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/ml2ls.py +0 -0
  250. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/mol.py +0 -0
  251. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/netfinder.py +0 -0
  252. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/nl2ls.py +0 -0
  253. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/ocr.py +0 -0
  254. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/plot.py +0 -0
  255. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/setuptools-70.1.0-py3-none-any.whl +0 -0
  256. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/sleep_events_detectors.py +0 -0
  257. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/stats.py +0 -0
  258. {py2ls-0.2.5.7 → py2ls-0.2.5.9}/py2ls/translator.py +0 -0
  259. {py2ls-0.2.5.7 → 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.7
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})")
5268
5329
 
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
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
5365
+
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):
@@ -6772,39 +6861,39 @@ def finfo(fpath):
6772
6861
 
6773
6862
 
6774
6863
  # ! format excel file
6775
- def hex2argb(hex_color):
6776
- """
6777
- Convert a hex color code to aARGB format required by openpyxl.
6778
6864
 
6779
- :param hex_color: A hex color code in the format #RRGGBB, RRGGBB, or aARRGGBB.
6780
- :return: A hex color code in the format aARRGGBB.
6781
6865
 
6782
- # Example usage
6783
- print(hex_to_argb("FFFF00")) # Outputs: FFFFFF00
6784
- print(hex_to_argb("#DF4245")) # Outputs: FFFFFF00
6785
- print(hex_to_argb("FF00FF00")) # Outputs: FF00FF00 (already in aARGB format)
6866
+ def hex2argb(color):
6786
6867
  """
6787
- # Remove the hash if present
6788
- if hex_color.startswith("#"):
6789
- hex_color = hex_color[1:]
6868
+ Convert a color name or hex code to aARGB format required by openpyxl.
6790
6869
 
6791
- # Check if it's already in aARGB format (8 characters)
6792
- if len(hex_color) == 8:
6793
- return hex_color
6870
+ :param color: A color in the format: 'blue', '#RRGGBB', 'RRGGBB', 'aARRGGBB'
6871
+ :return: A hex color code in the format aARRGGBB.
6794
6872
 
6795
- # Otherwise, assume it's in RRGGBB format and prepend FF for opaque
6796
- if len(hex_color) == 6:
6797
- return f"FF{hex_color}"
6798
- if len(hex_color) == 7:
6799
- return f"F{hex_color}"
6800
- else:
6801
- if len(hex_color) > 8:
6802
- return hex_color[-9:]
6803
- else:
6804
- return "F" * (9 - len(hex_color)) + hex_color
6805
- raise ValueError(
6806
- "Invalid hex color format. Use RRGGBB, #RRGGBB, or aARRGGBB format."
6807
- )
6873
+ Example:
6874
+ print(hex2argb("blue")) # Output: FF0000FF
6875
+ print(hex2argb("FFFF00")) # Output: FFFFFF00
6876
+ print(hex2argb("#DF4245")) # Output: FFDf4245
6877
+ print(hex2argb("FF00FF00")) # Output: FF00FF00 (already in aARGB format)
6878
+ """
6879
+ import matplotlib.colors as mcolors
6880
+ import re
6881
+ color = color.lower().replace(" ", "") # 'light blue'
6882
+ # Convert color name (e.g., "blue") to hex
6883
+ if color.lower() in mcolors.CSS4_COLORS:
6884
+ color = mcolors.CSS4_COLORS[color.lower()].lstrip("#")
6885
+ color = color.lstrip("#").upper()# Remove '#' if present
6886
+
6887
+ # Validate hex format
6888
+ if not re.fullmatch(r"[A-F0-9]{6,8}", color):
6889
+ raise ValueError(f"格式错误❌: {color}, 应该使用 RRGGBB, #RRGGBB, or aARRGGBB format.")
6890
+
6891
+ # If already in aARRGGBB format (8 chars), return as is
6892
+ if len(color) == 8:
6893
+ return color
6894
+
6895
+ # If in RRGGBB format, add FF (full opacity) as alpha
6896
+ return f"FF{color}"
6808
6897
 
6809
6898
  def extract_kwargs(func):
6810
6899
  import inspect
@@ -6975,7 +7064,7 @@ def format_excel(
6975
7064
  from openpyxl.worksheet.datavalidation import DataValidation
6976
7065
  from openpyxl.comments import Comment
6977
7066
  from openpyxl.formatting.rule import ColorScaleRule, DataBarRule, IconSetRule,IconSet
6978
-
7067
+ from openpyxl.utils import get_column_letter
6979
7068
  def convert_indices_to_range(row_slice, col_slice):
6980
7069
  """Convert numerical row and column slices to Excel-style range strings."""
6981
7070
  start_row = row_slice.start + 1
@@ -7000,9 +7089,17 @@ def format_excel(
7000
7089
  sheet_name : str
7001
7090
  The name of the sheet to style.
7002
7091
  conditions : dict
7003
- Dictionary defining conditions for text coloring.
7092
+ Dictionary defining conditions for text or background coloring.
7093
+ Example:
7094
+ {
7095
+ ">10": "#FF0000", # Red if value is greater than 10
7096
+ "contains:Error": "#FFFF00", # Yellow if text contains 'Error'
7097
+ "startswith:Warn": "#FFA500" # Orange if text starts with 'Warn'
7098
+ }
7004
7099
  cell_idx : tuple, optional
7005
7100
  A tuple of slices defining the selected row and column range (only for DataFrame).
7101
+ where : str, default="text"
7102
+ "text" -> Apply color to text, "bg" -> Apply color to background.
7006
7103
 
7007
7104
  Returns:
7008
7105
  openpyxl.workbook.workbook.Workbook
@@ -7010,14 +7107,24 @@ def format_excel(
7010
7107
  """
7011
7108
  def evaluate_condition(value, condition):
7012
7109
  """Evaluate the condition dynamically."""
7110
+ if not isinstance(conditions, dict):
7111
+ raise ValueError(f"condition必须是dict格式:e.g., {'x>=20':'#DD0531', 'startswith:Available':'#DD0531'}")
7013
7112
  try:
7014
7113
  if "x" in condition and re.search(r"[<>=!]=*", condition):
7015
7114
  expr = condition.replace("x", str(value))
7115
+ return eval(expr)
7116
+ elif condition.startswith("startswith:") or condition.startswith("startwith:"):
7117
+ return value.startswith(condition.split(":", 1)[1])
7118
+ elif condition.startswith("endswith:") or condition.startswith("endwith:"):
7119
+ return value.endswith(condition.split(":", 1)[1])
7120
+ elif condition.startswith("contains:") or condition.startswith("contain:") or condition.startswith("include:"):
7121
+ return condition.split(":", 1)[1] in value
7122
+ elif condition.startswith("matches:") or condition.startswith("match:"):
7123
+ return re.search(condition.split(":", 1)[1], value) is not None
7016
7124
  else:
7017
7125
  expr = condition
7018
- return eval(expr)
7019
- except Exception as e:
7020
- # print(f"Error evaluating condition {condition} for value {value}: {e}")
7126
+ return False
7127
+ except Exception as e:
7021
7128
  return False
7022
7129
 
7023
7130
  def apply_condition_to_cell_text_color(cell, value):
@@ -7446,12 +7553,12 @@ def format_excel(
7446
7553
  kwargs.pop("sheet_name", 0) # 更好地跟df.to_excel结合使用
7447
7554
  # 只有openpyxl才支持 append
7448
7555
  mode = strcmp(kwargs.get("mode", "a"), ["a", "w","auto"])[0]
7449
- print(f'mode="{mode}"')
7556
+ # print(f'mode="{mode}"')
7450
7557
  kwargs.pop("mode", None)
7451
7558
  engine = strcmp(kwargs.get("engine", "openpyxl"), ["xlsxwriter", "openpyxl"])[0]
7452
7559
  # corr engine
7453
7560
  engine="openpyxl" if mode=="a" else "xlsxwriter"
7454
- print(f'engine="{engine}"')
7561
+ # print(f'engine="{engine}"')
7455
7562
  if_sheet_exists=kwargs.get("if_sheet_exists","replace")
7456
7563
  # 通常是不需要保存index的
7457
7564
  index = kwargs.get("index", False)
@@ -7478,11 +7585,7 @@ def format_excel(
7478
7585
  with pd.ExcelWriter(filename, mode="a", engine=engine, if_sheet_exists=if_sheet_exists) as writer:
7479
7586
  for ws in df.worksheets: # Iterate through worksheets in the input workbook
7480
7587
  ws_df = pd.DataFrame(ws.values)
7481
- ws_df.to_excel(writer,
7482
- sheet_name=sheet_name,
7483
- index=index,
7484
- header=header,
7485
- **kwargs)
7588
+ ws_df.to_excel(writer,sheet_name=sheet_name,index=index,header=header,**kwargs)
7486
7589
  # 重新打开刚更新过的数据
7487
7590
  wb = load_workbook(filename)
7488
7591
  if sheet_name in wb.sheetnames:
@@ -8008,21 +8111,20 @@ def format_excel(
8008
8111
  pil_img=img_path = None
8009
8112
  if isinstance(img_data, dict):
8010
8113
  if "path" in img_data:
8011
- img_path = img_data["path"] # File path
8012
- img_ = drawing.image.Image(img_path)
8114
+ img_ = drawing.image.Image(img_data["path"])# File path
8013
8115
  elif "image" in img_data:
8014
- pil_img = img_data["image"] # PIL Image object
8116
+ img_ = drawing.image.Image(img_data["image"])# PIL Image object
8015
8117
  elif "array" in img_data:
8016
- 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
8017
8119
 
8018
8120
  img_width = img_data.get("width", None)
8019
8121
  img_height = img_data.get("height", None)
8020
8122
  elif isinstance(img_data, str):
8021
- img_path = img_data # Direct file path
8123
+ img_ = drawing.image.Image(img_data)# Direct file path
8022
8124
  elif isinstance(img_data, (PIL.Image.Image,PIL.PngImagePlugin.PngImageFile)):
8023
- pil_img = img_data # Direct PIL Image object
8125
+ img_ = drawing.image.Image(img_data)# Direct PIL Image object
8024
8126
  elif isinstance(img_data, np.ndarray):
8025
- 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
8026
8128
  elif pil_img:
8027
8129
  img_ = drawing.image.Image(pil_img)
8028
8130
 
@@ -8216,7 +8318,89 @@ def _df_outlier(
8216
8318
 
8217
8319
  return processed_data
8218
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
8219
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
8220
8404
  def df_outlier(
8221
8405
  data,
8222
8406
  columns=None,
@@ -12506,3 +12690,83 @@ def py2installer(
12506
12690
  raise
12507
12691
 
12508
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.7"
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"