py2ls 0.1.10.23__tar.gz → 0.1.10.25__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.
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/PKG-INFO +1 -1
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/batman.py +78 -16
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/ips.py +220 -53
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/netfinder.py +2 -2
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/ocr.py +45 -34
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/plot.py +46 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/pyproject.toml +1 -1
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/README.md +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.DS_Store +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/COMMIT_EDITMSG +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/FETCH_HEAD +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/HEAD +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/config +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/description +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/hooks/applypatch-msg.sample +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/hooks/commit-msg.sample +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/hooks/fsmonitor-watchman.sample +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/hooks/post-update.sample +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/hooks/pre-applypatch.sample +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/hooks/pre-commit.sample +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/hooks/pre-merge-commit.sample +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/hooks/pre-push.sample +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/hooks/pre-rebase.sample +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/hooks/pre-receive.sample +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/hooks/prepare-commit-msg.sample +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/hooks/push-to-checkout.sample +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/hooks/update.sample +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/index +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/info/exclude +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/logs/HEAD +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/logs/refs/heads/main +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/logs/refs/remotes/origin/HEAD +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/logs/refs/remotes/origin/main +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/01/d5bd8065e6860c0bd23ff9fa57161806a099e1 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/09/08da26de58c114225ad81f484b80bf5d351b34 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/0b/409e1bc918277010f5679b402d1d1dda53e15c +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/12/c2808a1b3a4d0892a4154dfba1e2ae3770fa73 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/14/449a0e6ba4ea2f1a73acf63ef91c9c6193f9ed +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/15/a8e468aacfcb440e090020f36d0b985d45da23 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/1a/b4585881a6a42889f01aa0cfe25fd5acfaf46f +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/1c/3f92adda34344bcbbbf9d409c79855ae2aaea8 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/1c/9314c5f69b9390068a2a8616875d974849d71f +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/1d/fe9d9633b24ea560354f4f93d39c6e5f163ea0 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/20/72c28e83f4347959d29f7b3a6c1fc3e4ee6b59 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/24/6b368b986f758630c46dc02b7fa512b53422f7 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/25/b796accd261b9135fd32a2c00785f68edf6c46 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/27/aa6074f652bc6f7078f8647489d9ee8e24f0e2 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/28/c2969d785c1b892c2a96b3f00eba63a59811b3 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/2a/ae95d517d213b660bf4f65a4e0cfae7bb893eb +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/2a/fdf45791a26d42ccead35ace76a8f0b2a56561 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/30/a2f8da47ee947811dc8d993f5a06a45de374f4 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/32/fd627b62fad7cf3b2f9e34ab9777126a0987ad +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/34/9e31b6a3634cea102ce5588b98c11cc1738605 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/34/b6f3a2ee84f39bed4eee57f2c0e0afb994feb1 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/35/1a5f491ab97eee9d1ee699478d75a8bb5d3dc2 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/36/b4a1b7403abc6c360f8fe2cb656ab945254971 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/36/e56a361f526eafa59c5235a5c990bf288b5f9c +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/36/ef43e50009e59db11812c258846d9e38718173 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/39/7ead045fbbcfb17c62019eb18fe21ed05dbee5 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/39/b13be65125556784e44c7a1d9821703c7ab67e +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/3b/507acc7f23391644cc0b824b1e79fd2677a362 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/3b/bd972aa7ad680858f8dfbd0f7fcd97756f0d6f +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/3c/bbe5f4173d165127b9ad96119f1ec24c306ffc +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/3d/9d10d27724657a436c65a6254bfd213d4b3562 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/3f/d6561300938afbb3d11976cf9c8f29549280d9 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/41/dcf4b3bf0460946b2da93776cf9e836d62178f +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/43/dbd49b2ee367c5434dd545e3b5795434f2ef0b +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/45/b1b6178bacbfc997811a998b5cc60c1ea7fac8 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/47/6cbd5a7c5e35cddef2f8a38bdc4896d403b095 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/48/a88fc5806305d0bb0755ee6801161b79696972 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/4f/7afb40dff2153d857fc85748c2eecb85125042 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/50/08ddfcf53c02e82d7eee2e57c38e5672ef89f6 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/53/e0deb1cb4c2c606bced6e7f9a66b0fda60980d +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/56/e4e8b2d5545e0256090f45aa8fc42c5fe067d0 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/57/63d0c52f5c9c69e89d514a1f96034947abe21a +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/57/bd1c0199483ab316235b094543b85edec6c35e +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/58/20a729045d4dc7e37ccaf8aa8eec126850afe2 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/59/380c4c26bdcd4d9b71ae3e2e35f05b3f26c5ab +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/5a/192565abf89c9d765af846ce6d53a92b1ce7ad +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/60/f273eb1c412d916fa3f11318a7da7a9911b52a +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/61/570cec8c061abe74121f27f5face6c69b98f99 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/62/4488173ed2c8936fa5cea3cf5dd3f26a30b86e +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/62/7c81b23b4e56e87b042b650b0103653cc9e34a +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/62/d90ccf8cbefdc2e4fd475e7c6f4f76e9fdf801 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/63/100154b27846e8010e55b6bf4b3d7762c14c5f +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/64/27a4edff08f93d98f511418423f09f2ab90bcd +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/66/6227eeeba24073e63811e89f1449f3d958f183 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/66/c998778721d424bd0aae80602dabbffa93af2e +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/68/6df3072c8b025fb18106ed2df505994ad062a9 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/69/13c452ca319f7cbf6a0836dc10a5bb033c84e4 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/6a/52e747a2b349b128d1490d9e896d2323818eb7 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/6b/7fde264d93a7a0986d394c46c7650d0ce2ab92 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/6c/cebb29b7f3f5b0c889f6dadbf9ff066554587d +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/6d/c2cdf4a84e538e5d4777486aeff87e42f41799 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/6d/ee29dbdcc84edeeacede105110446f3ccac963 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/71/36b2074a2754be8b58127d82250e5b37e3c373 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/72/245a05b0966011cb381e6b32b0465000e969ab +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/72/e4179337639859678ddaecf38b16f33aaec8e1 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/78/063f4c863fc371ec0313303c0a81283b35d9b6 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/78/3d4167bc95c9d2175e0df03ef1c1c880ba75ab +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/79/7ae089b2212a937840e215276005ce76881307 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/7e/5956c806b5edc344d46dab599dec337891ba1f +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/81/8f26b7bf042269729020cf944fc362d66ba27e +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/82/70b319ce4046854fbe7dc41054b6c2d112dab2 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/84/59071b722a255b774a80b27746033f8141ab39 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/85/aee46f478e9afdb84d50a05242c53b04ed2e21 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/86/e288b46f8fe179907e4413f665aeb5053fddb1 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/87/ef1fc3f7f1ddc4d0ab9b3e65381ce9f3388621 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/8b/84f56978e1de8f2ae82abce5f8b3e182d365cd +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/8e/55a7d2b96184030211f20c9b9af201eefcac82 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/91/c69ad88fe0ba94aa7859fb5f7edac5e6f1a3f7 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/94/74152b4b463d70ae5ad07f0c658be3e296026b +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/94/f7dbe88e80c4205a901b71eb8f181974376bba +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/97/1aef09ea939f46b60b9646f8d524c78a9220f4 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/9b/ec5ee2236ee2d5532c36bfd132e23c58fdb69c +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/9d/0df52899fe95279059286d9c0ec42287edc168 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/a1/5389729850729fc7bd78a54f26fce77f30be12 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/a1/906da89d1174f74867800c74c43af36253bd5e +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/a4/63fdd23e5efd713db8a71f316f3a1c7bd60916 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/a5/ec8f74642fbba27f7ea78c53b372ae0c7dedce +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/a7/3e13eafee65c5b8d73ad2d3ea46d0eee82f0d3 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/b0/56be4be89ba6b76949dd641df45bb7036050c8 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/b0/9cd7856d58590578ee1a4f3ad45d1310a97f87 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/b2/18e6a0f0f1c4df8cdefa9852058348abc713b7 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/b3/4f7f271c6d6105e35a6556ffda71d03afe8c96 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/b3/69579064bde9de9a19d114fc33e4e48cc8c0e4 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/b5/61831c7dce8ea51e7ee6b6fa35745f14d8242d +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/b7/2c9e75ab7d0afe594664650aa8f6c772f5ac64 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/bb/81ccc0513f18fc160b54a82861e9a80d23f4f6 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/bb/934eb33bc1a8b85630bf680caffd99560c1b8f +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/bf/67907e337021ebff434e02b19b30a741c144af +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/bf/b54d65922ce1dfda1aaa014913a54e7172d0bc +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/c1/20fc812b9ad311c34a3608512d6a9d976bb48e +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/c1/397c6ed72c4e20ef6b9ab83163e9a6baba5b45 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/c4/cba65f1163661999ee4b8ed23342b63bc1300c +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/c6/7f17e5707313600efcb85e9a3fedea35dba591 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/c6/f32aced880bd165a251cb52b26b0c1107e2141 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/cc/45df1d317a2eb63ff1ff3a5f3b4a9f98fd92b5 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/cd/822b3574a88ebdd1ed82fd6983f37e626d52b4 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/cf/0c0d9c6fb09473aaeb7f7e2edbd770c3f2ef3d +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/d2/992df305f4b56a466a2f221aeb182ddd20f418 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/d6/39e8af592cd75a318d8affddd1bcc70c2095f2 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/d6/9ab1c4aadf279936dd778e8346ba60f74705b6 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/d8/4688b54c0040a30976b3a6540bc47adf7ce680 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/d9/005f2cc7fc4e65f14ed5518276007c08cf2fd0 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/d9/c2403fd166ce791b4e9d0c6792ed8342c71fcd +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/d9/dfa5aee51e92a541b707e8e7baea6f06deff98 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/db/141dbaa93594df2a8156182f361ee4db829359 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/db/3f2cd643292057936230b95cf7ec3046affe11 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/db/ffa8ea7bda721d0cee7b9e4ce5b2ef927733ff +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/dc/c2bdbafb3296e09d9ee4955cfa55d275825f94 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/dc/cdbd4266765d840be2ae35ab1752a0fa312c16 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/dd/87fb5f606fe380d81e6fe3a2c98f9f99e3e09b +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/de/214c626ac2dd2685bfaa0bc0fc20f528d014d7 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/df/e0770424b2a19faf507a501ebfc23be8f54e7b +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/e2/f2f8f4c25e62a297fc55f36acc6b01cfbab76f +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/e3/1356f90ea6dd0577b5e0b40b206319adcbf085 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/e3/5a4dafc50850cacac7bf76c56db2715cbda2c4 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/e4/6c715352db9fe3c887a635f1916df4ca1f4ff9 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/e5/0580a0bd1e1b3d29f834382b80fceb61d5cf0c +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/e9/391ffe371f1cc43b42ef09b705d9c767c2e14f +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/ea/3a18cc75e53792744ef754e05d3f4481768c13 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/ec/40fd8bf8e4c342534a9fc020289e402ba6bc9d +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/ec/d980279432b13f0374b90ca439a6329cdece0f +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/ee/cee64eacaff022dcdc509c0c2b1da492f21060 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/f1/e50757fddc28b445545dc7e2759b54cdd0f42e +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/f4/b64d3107b39e3ad6f540c6607004ea34e6c024 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/f4/ba7f815b886797b73fede071d86e0c134d2bc7 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/f5/61c3c1bf1c9ea9c9d1f556a7be2869f71f3bdf +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/f6/44a8ff56fa035105fc517cbb1ac46c3d8e349a +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/f7/c98ba5c2f903e603b1f5e63d49fbc8a43815cc +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/f9/045a08e96eb76848fc4d68e3e3e687cca39a2d +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/fa/147e6bb78a2e8db241d231295fd7f1ed061af8 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/objects/fc/292e793ecfd42240ac43be407023bd731fa9e7 +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/refs/heads/main +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/refs/remotes/origin/HEAD +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.git/refs/remotes/origin/main +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.gitattributes +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/.gitignore +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/LICENSE +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/README.md +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/__init__.py +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/brain_atlas.py +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/chat.py +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/correlators.py +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/.DS_Store +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/db2ls_sql_chtsht.json +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/docs_links.json +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/lang_code_iso639.json +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/example/style1.pdf +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/example/style2.pdf +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/example/style3.pdf +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/example/style4.pdf +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/example/style5.pdf +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/example/style6.pdf +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/example/style7.pdf +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/example/style8.pdf +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/example/style9.pdf +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/style1.json +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/style10.json +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/style11.json +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/style12.json +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/style2.json +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/style3.json +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/style4.json +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/style5.json +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/style6.json +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/style7.json +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/style8.json +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/data/styles/style9.json +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/db2ls.py +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/doc.py +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/export_requirements.py +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/freqanalysis.py +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/ich2ls.py +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/setuptools-70.1.0-py3-none-any.whl +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/sleep_events_detectors.py +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/stats.py +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/translator.py +0 -0
- {py2ls-0.1.10.23 → py2ls-0.1.10.25}/py2ls/wb_detector.py +0 -0
@@ -3,33 +3,75 @@ from email.mime.text import MIMEText
|
|
3
3
|
from email.mime.multipart import MIMEMultipart
|
4
4
|
from email.mime.base import MIMEBase
|
5
5
|
from email import encoders
|
6
|
-
import schedule
|
7
6
|
import time
|
8
7
|
from datetime import datetime
|
9
8
|
import os
|
10
9
|
from pprint import pp
|
11
10
|
import json
|
11
|
+
import mimetypes
|
12
|
+
import sys
|
12
13
|
|
13
14
|
|
14
|
-
|
15
|
-
def convert_to_html(text_list):
|
15
|
+
def convert_to_html(text_list, strict=False):
|
16
16
|
if not isinstance(text_list, list):
|
17
17
|
text_list = [text_list]
|
18
18
|
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
19
|
+
# Define a mapping for escape sequences to their HTML representations
|
20
|
+
escape_mapping = {
|
21
|
+
"\\": "\", # Backslash
|
22
|
+
"'": "'", # Single quote
|
23
|
+
'"': """, # Double quote
|
24
|
+
"\n": "<br>", # Newline
|
25
|
+
"\r": "", # Carriage return (not represented in HTML)
|
26
|
+
"\t": " ", # Tab (4 spaces)
|
27
|
+
"\b": "", # Backspace (not typically represented)
|
28
|
+
"\f": "", # Form feed (not typically represented)
|
29
|
+
"\v": "", # Vertical tab (not typically represented)
|
30
|
+
"\a": "", # Bell/alert sound (not typically represented)
|
31
|
+
"\0": "", # Null character (not typically represented)
|
32
|
+
}
|
33
|
+
# Convert text by replacing escape sequences with their HTML equivalents
|
34
|
+
html_content = ""
|
35
|
+
for text in text_list:
|
36
|
+
for escape_seq, html_rep in escape_mapping.items():
|
37
|
+
text = text.replace(escape_seq, html_rep)
|
38
|
+
html_content += text.replace("\n", "<br>") # Add line breaks for newlines
|
39
|
+
if strict:
|
40
|
+
html_content = "<html><body>\n" + html_content + "\n</body></html>"
|
26
41
|
return html_content
|
27
42
|
|
28
43
|
|
44
|
+
def get_name(email_str, by="@"):
|
45
|
+
if "num" in by:
|
46
|
+
for i, char in enumerate(email_str):
|
47
|
+
if char.isdigit():
|
48
|
+
break
|
49
|
+
else:
|
50
|
+
return email_str
|
51
|
+
return email_str[:i]
|
52
|
+
|
53
|
+
# Handle the case where '@' is the criteria
|
54
|
+
elif "@" in by:
|
55
|
+
name = email_str.split("@")[0]
|
56
|
+
name = get_name(name, by="num")
|
57
|
+
name = " ".join([part.capitalize() for part in name.split(".")])
|
58
|
+
return name
|
59
|
+
|
60
|
+
|
29
61
|
def extract_kv(
|
30
|
-
dir_data=
|
62
|
+
dir_data=None,
|
31
63
|
idx=0,
|
32
64
|
): # select the index
|
65
|
+
if dir_data is None:
|
66
|
+
if "dar" in sys.platform:
|
67
|
+
dir_data = "/Users/macjianfeng/Dropbox/github/python/py2ls/confidential_data/gmail_login.json"
|
68
|
+
else:
|
69
|
+
if "win" in sys.platform:
|
70
|
+
dir_data = (
|
71
|
+
"Z:\\Jianfeng\\Apps\settings\\confidential_data\\gmail_login.json"
|
72
|
+
)
|
73
|
+
elif "lin" in sys.platform:
|
74
|
+
dir_data = "/Users/macjianfeng/Dropbox/github/python/py2ls/confidential_data/gmail_login.json"
|
33
75
|
with open(dir_data, "r") as file:
|
34
76
|
email_login = json.load(file)
|
35
77
|
for i, (user, pd) in enumerate(email_login.items()):
|
@@ -38,6 +80,10 @@ def extract_kv(
|
|
38
80
|
|
39
81
|
|
40
82
|
def email_to(**kwargs):
|
83
|
+
return email(**kwargs)
|
84
|
+
|
85
|
+
|
86
|
+
def email(**kwargs):
|
41
87
|
"""
|
42
88
|
usage:
|
43
89
|
email_to(who="example@gmail.com",
|
@@ -106,7 +152,14 @@ def email_to(**kwargs):
|
|
106
152
|
what = ""
|
107
153
|
if isinstance(what, list):
|
108
154
|
what = convert_to_html(what)
|
109
|
-
if 'class="
|
155
|
+
if 'class="' in str(what):
|
156
|
+
# Combine HTML content correctly
|
157
|
+
html_content = "<html><body>\n"
|
158
|
+
html_content += f"{what}"
|
159
|
+
html_content += f"<br><br>{convert_to_html([signature])}"
|
160
|
+
html_content += "\n</body></html>"
|
161
|
+
message.attach(MIMEText(html_content, "html"))
|
162
|
+
elif 'class="' in str(attachments):
|
110
163
|
# Combine HTML content correctly
|
111
164
|
html_content = "<html><body>\n"
|
112
165
|
html_content += f"{convert_to_html(what)}<br>{attachments}"
|
@@ -124,15 +177,24 @@ def email_to(**kwargs):
|
|
124
177
|
if isinstance(attachments, str):
|
125
178
|
attachments = [attachments]
|
126
179
|
for file in attachments:
|
127
|
-
|
180
|
+
# 有时候一些不常用的文件类型, 无法自动识别
|
181
|
+
mime_type, _ = mimetypes.guess_type(file)
|
182
|
+
if mime_type is None:
|
183
|
+
if file.endswith(".xlsx"):
|
184
|
+
mime_type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
185
|
+
else:
|
186
|
+
mime_type = "application/octet-stream"
|
187
|
+
|
188
|
+
main_type, sub_type = mime_type.split("/", 1)
|
189
|
+
# part = MIMEBase("application", "octet-stream") # 旧的版本
|
190
|
+
part = MIMEBase(main_type, sub_type)
|
128
191
|
try:
|
129
192
|
with open(file, "rb") as attachment:
|
130
193
|
part.set_payload(attachment.read())
|
131
194
|
encoders.encode_base64(part)
|
132
|
-
|
195
|
+
filename = os.path.basename(file)
|
133
196
|
part.add_header(
|
134
|
-
"Content-Disposition",
|
135
|
-
f'attachment; filename= "{os.path.basename(file)}"',
|
197
|
+
"Content-Disposition", f'attachment; filename="{filename}"'
|
136
198
|
)
|
137
199
|
message.attach(part)
|
138
200
|
except FileNotFoundError:
|
@@ -58,6 +58,18 @@ except NameError:
|
|
58
58
|
pass
|
59
59
|
|
60
60
|
|
61
|
+
|
62
|
+
|
63
|
+
# set 'dir_save'
|
64
|
+
if 'dar' in sys.platform:
|
65
|
+
dir_save = "/Users/macjianfeng/Dropbox/Downloads/"
|
66
|
+
else:
|
67
|
+
if 'win' in sys.platform:
|
68
|
+
dir_save= "Z:\\Jianfeng\\temp\\"
|
69
|
+
elif 'lin' in sys.platform:
|
70
|
+
dir_data="/Users/macjianfeng/Dropbox/github/python/py2ls/confidential_data/gmail_login.json"
|
71
|
+
|
72
|
+
|
61
73
|
def unique(lst, ascending=None):
|
62
74
|
"""
|
63
75
|
移除列表中的重复元素,同时可以选择按升序或降序排序。
|
@@ -260,10 +272,6 @@ def upgrade(module="py2ls"):
|
|
260
272
|
except subprocess.CalledProcessError as e:
|
261
273
|
print(f"An error occurred while upgrading py2ls: {e}")
|
262
274
|
|
263
|
-
|
264
|
-
dir_save = "/Users/macjianfeng/Dropbox/Downloads/"
|
265
|
-
|
266
|
-
|
267
275
|
def get_version(pkg):
|
268
276
|
import importlib.metadata
|
269
277
|
|
@@ -749,6 +757,41 @@ def num2str(num, *args, **kwargs):
|
|
749
757
|
# num2str(12345333.6789, sep=","), type(num2str(12345.6789, ","))
|
750
758
|
# ) # Output: "12,345.6789"
|
751
759
|
# print(num2str(7000.00, sep=","), type(num2str(7000.00, ","))) # Output: "7,000.00"
|
760
|
+
|
761
|
+
|
762
|
+
# Helper to convert text or list of text to HTML
|
763
|
+
def str2html(text_list, strict=False):
|
764
|
+
if not isinstance(text_list, list):
|
765
|
+
text_list = [text_list]
|
766
|
+
|
767
|
+
# Define a mapping for escape sequences to their HTML representations
|
768
|
+
escape_mapping = {
|
769
|
+
"\\": "\", # Backslash
|
770
|
+
"'": "'", # Single quote
|
771
|
+
'"': """, # Double quote
|
772
|
+
"\n": "<br>", # Newline
|
773
|
+
"\r": "", # Carriage return (not represented in HTML)
|
774
|
+
"\t": " ", # Tab (4 spaces)
|
775
|
+
"\b": "", # Backspace (not typically represented)
|
776
|
+
"\f": "", # Form feed (not typically represented)
|
777
|
+
"\v": "", # Vertical tab (not typically represented)
|
778
|
+
"\a": "", # Bell/alert sound (not typically represented)
|
779
|
+
"\0": "", # Null character (not typically represented)
|
780
|
+
}
|
781
|
+
|
782
|
+
# Convert text by replacing escape sequences with their HTML equivalents
|
783
|
+
html_content = ""
|
784
|
+
for text in text_list:
|
785
|
+
for escape_seq, html_rep in escape_mapping.items():
|
786
|
+
text = text.replace(escape_seq, html_rep)
|
787
|
+
html_content += text.replace("\n", "<br>") # Add line breaks for newlines
|
788
|
+
|
789
|
+
if strict:
|
790
|
+
html_content = "<html><body>\n" + html_content + "\n</body></html>"
|
791
|
+
|
792
|
+
return html_content
|
793
|
+
|
794
|
+
|
752
795
|
def sreplace(*args, **kwargs):
|
753
796
|
"""
|
754
797
|
sreplace(text, by=None, robust=True)
|
@@ -1443,10 +1486,21 @@ def fappend(fpath, content=None):
|
|
1443
1486
|
file.write(content)
|
1444
1487
|
|
1445
1488
|
|
1489
|
+
def filter_kwargs(kws, valid_kwargs):
|
1490
|
+
if isinstance(valid_kwargs, dict):
|
1491
|
+
kwargs_filtered = {
|
1492
|
+
key: value for key, value in kws.items() if key in valid_kwargs.keys()
|
1493
|
+
}
|
1494
|
+
elif isinstance(valid_kwargs, list):
|
1495
|
+
kwargs_filtered = {
|
1496
|
+
key: value for key, value in kws.items() if key in valid_kwargs
|
1497
|
+
}
|
1498
|
+
return kwargs_filtered
|
1499
|
+
|
1500
|
+
|
1446
1501
|
def fsave(
|
1447
1502
|
fpath,
|
1448
1503
|
content,
|
1449
|
-
mode="w",
|
1450
1504
|
how="overwrite",
|
1451
1505
|
kind=None,
|
1452
1506
|
font_name="Times",
|
@@ -1468,7 +1522,7 @@ def fsave(
|
|
1468
1522
|
None
|
1469
1523
|
"""
|
1470
1524
|
|
1471
|
-
def save_content(fpath, content, mode=
|
1525
|
+
def save_content(fpath, content, mode="w", how="overwrite"):
|
1472
1526
|
if "wri" in how.lower():
|
1473
1527
|
with open(fpath, mode, encoding="utf-8") as file:
|
1474
1528
|
file.write(content)
|
@@ -1515,13 +1569,36 @@ def fsave(
|
|
1515
1569
|
pdf.output(fpath, "F")
|
1516
1570
|
|
1517
1571
|
def save_csv(fpath, data, **kwargs):
|
1572
|
+
# https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_csv.html
|
1573
|
+
kwargs_csv = dict(
|
1574
|
+
path_or_buf=None,
|
1575
|
+
sep=",",
|
1576
|
+
na_rep="",
|
1577
|
+
float_format=None,
|
1578
|
+
columns=None,
|
1579
|
+
header=True,
|
1580
|
+
index=True,
|
1581
|
+
index_label=None,
|
1582
|
+
mode="w",
|
1583
|
+
encoding=None,
|
1584
|
+
compression="infer",
|
1585
|
+
quoting=None,
|
1586
|
+
quotechar='"',
|
1587
|
+
lineterminator=None,
|
1588
|
+
chunksize=None,
|
1589
|
+
date_format=None,
|
1590
|
+
doublequote=True,
|
1591
|
+
escapechar=None,
|
1592
|
+
decimal=".",
|
1593
|
+
errors="strict",
|
1594
|
+
storage_options=None,
|
1595
|
+
)
|
1596
|
+
kwargs_valid = filter_kwargs(kwargs, kwargs_csv)
|
1518
1597
|
df = pd.DataFrame(data)
|
1519
|
-
df.to_csv(fpath, **
|
1598
|
+
df.to_csv(fpath, **kwargs_valid)
|
1520
1599
|
|
1521
1600
|
def save_xlsx(fpath, data, **kwargs):
|
1522
|
-
|
1523
|
-
if format:
|
1524
|
-
kwargs.pop("format", None)
|
1601
|
+
if any(kwargs):
|
1525
1602
|
format_excel(df=data, filename=fpath, **kwargs)
|
1526
1603
|
else:
|
1527
1604
|
kwargs.pop("format", None)
|
@@ -1618,7 +1695,7 @@ def fsave(
|
|
1618
1695
|
print(
|
1619
1696
|
f"Warning:\n{kind} is not in the supported list ['docx', 'txt', 'md', 'html', 'pdf', 'csv', 'xlsx', 'json', 'xml', 'yaml']"
|
1620
1697
|
)
|
1621
|
-
|
1698
|
+
mode = kwargs.get("mode", "w")
|
1622
1699
|
if kind == "docx" or kind == "doc":
|
1623
1700
|
save_docx(fpath, content, font_name, font_size, spacing)
|
1624
1701
|
elif kind == "txt":
|
@@ -1735,46 +1812,66 @@ def sort_kind(df, by="name", ascending=True):
|
|
1735
1812
|
sorted_df = df.iloc[sorted_index].reset_index(drop=True)
|
1736
1813
|
return sorted_df
|
1737
1814
|
|
1738
|
-
|
1739
|
-
def isa(*args, **kwargs):
|
1815
|
+
def isa(content, kind):
|
1740
1816
|
"""
|
1741
|
-
|
1742
|
-
|
1817
|
+
content, kind='img'
|
1818
|
+
kinds file paths based on the specified kind.
|
1743
1819
|
Args:
|
1744
|
-
|
1745
|
-
|
1820
|
+
content (str): Path to the file.
|
1821
|
+
kind (str): kind of file to kind. Default is 'img' for images. Other options include 'doc' for documents,
|
1746
1822
|
'zip' for ZIP archives, and 'other' for other types of files.
|
1747
1823
|
Returns:
|
1748
|
-
bool: True if the file matches the
|
1824
|
+
bool: True if the file matches the kind, False otherwise.
|
1749
1825
|
"""
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1753
|
-
|
1754
|
-
|
1755
|
-
|
1756
|
-
|
1757
|
-
return
|
1758
|
-
elif "
|
1759
|
-
return
|
1760
|
-
elif "
|
1761
|
-
return
|
1762
|
-
elif "
|
1763
|
-
|
1764
|
-
):
|
1765
|
-
return
|
1766
|
-
elif "
|
1767
|
-
|
1768
|
-
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1772
|
-
|
1773
|
-
|
1826
|
+
if "img" in kind.lower() or "image" in kind.lower():
|
1827
|
+
return is_image(content)
|
1828
|
+
elif "doc" in kind.lower():
|
1829
|
+
return is_document(content)
|
1830
|
+
elif "zip" in kind.lower():
|
1831
|
+
return is_zip(content)
|
1832
|
+
elif "dir" in kind.lower() or ("f" in kind.lower() and "d" in kind.lower()):
|
1833
|
+
return os.path.isdir(content)
|
1834
|
+
elif "fi" in kind.lower(): # file
|
1835
|
+
return os.path.isfile(content)
|
1836
|
+
elif "num" in kind.lower(): # file
|
1837
|
+
return os.path.isfile(content)
|
1838
|
+
elif "text" in kind.lower() or "txt" in kind.lower(): # file
|
1839
|
+
return is_text(content)
|
1840
|
+
elif "color" in kind.lower(): # file
|
1841
|
+
return is_str_color(content)
|
1842
|
+
elif "html" in kind.lower():
|
1843
|
+
# Remove leading and trailing whitespace
|
1844
|
+
content = content.strip()
|
1845
|
+
# Check for common HTML tags using regex
|
1846
|
+
# This pattern matches anything that looks like an HTML tag
|
1847
|
+
tag_pattern = r"<[a-zA-Z][^>]*>(.*?)</[a-zA-Z][^>]*>"
|
1848
|
+
# Check for any opening and closing tags
|
1849
|
+
if re.search(tag_pattern, content):
|
1850
|
+
return True
|
1851
|
+
# Additional checks for self-closing tags
|
1852
|
+
self_closing_tags = ["img", "br", "hr", "input", "meta", "link"]
|
1853
|
+
for tag in self_closing_tags:
|
1854
|
+
if f"<{tag}" in content:
|
1855
|
+
return True
|
1856
|
+
return False
|
1774
1857
|
else:
|
1775
|
-
print(f"{
|
1858
|
+
print(f"{kind} was not set up correctly")
|
1776
1859
|
return False
|
1777
1860
|
|
1861
|
+
import sys
|
1862
|
+
def get_os():
|
1863
|
+
os_name = sys.platform
|
1864
|
+
if "dar" in os_name:
|
1865
|
+
return "macOS"
|
1866
|
+
else:
|
1867
|
+
if "win" in os_name:
|
1868
|
+
return "Windows"
|
1869
|
+
elif "linux" in os_name:
|
1870
|
+
return "Linux"
|
1871
|
+
else:
|
1872
|
+
print(f"{os_name}, returned 'None'")
|
1873
|
+
return None
|
1874
|
+
|
1778
1875
|
|
1779
1876
|
def listdir(
|
1780
1877
|
rootdir,
|
@@ -3186,7 +3283,13 @@ def hex2argb(hex_color):
|
|
3186
3283
|
# Otherwise, assume it's in RRGGBB format and prepend FF for opaque
|
3187
3284
|
if len(hex_color) == 6:
|
3188
3285
|
return f"FF{hex_color}"
|
3189
|
-
|
3286
|
+
if len(hex_color) == 7:
|
3287
|
+
return f"F{hex_color}"
|
3288
|
+
else:
|
3289
|
+
if len(hex_color) > 8:
|
3290
|
+
return hex_color[-9:]
|
3291
|
+
else:
|
3292
|
+
return "F" * (9 - len(hex_color)) + hex_color
|
3190
3293
|
raise ValueError(
|
3191
3294
|
"Invalid hex color format. Use RRGGBB, #RRGGBB, or aARRGGBB format."
|
3192
3295
|
)
|
@@ -3540,7 +3643,6 @@ def format_excel(
|
|
3540
3643
|
number_format=None, # dict: e.g., {1:"0.00", 2:"#,##0",3:"0%",4:"$#,##0.00"}
|
3541
3644
|
data_validation=None, # dict
|
3542
3645
|
conditional_format=None, # dict
|
3543
|
-
index_default=False,
|
3544
3646
|
**kwargs,
|
3545
3647
|
):
|
3546
3648
|
if not isinstance(df, pd.DataFrame):
|
@@ -3711,15 +3813,29 @@ format_excel(
|
|
3711
3813
|
print(func_xample)
|
3712
3814
|
return None
|
3713
3815
|
kwargs.pop("format", None) # 更好地跟fsave结合使用
|
3816
|
+
kwargs.pop("sheet_name", None) # 更好地跟df.to_excel结合使用
|
3817
|
+
sheet_name_corr = (
|
3818
|
+
sheet_name if isinstance(sheet_name, str) else f"Sheet_{sheet_name}"
|
3819
|
+
)
|
3714
3820
|
|
3715
|
-
#
|
3716
|
-
|
3717
|
-
|
3718
|
-
|
3719
|
-
|
3821
|
+
# 只有openpyxl才支持 append
|
3822
|
+
mode = strcmp(kwargs.get("mode", "w"), ["a", "w"])[0]
|
3823
|
+
kwargs.pop("mode", None)
|
3824
|
+
engine = strcmp(kwargs.get("engine", "openpyxl"), ["xlsxwriter", "openpyxl"])[0]
|
3825
|
+
# 通常是不需要保存index的
|
3826
|
+
index = kwargs.get("index", False)
|
3827
|
+
kwargs.pop("index", None)
|
3828
|
+
# save file
|
3829
|
+
with pd.ExcelWriter(filename, mode=mode, engine=engine) as writer:
|
3830
|
+
df.to_excel(writer, sheet_name=sheet_name_corr, index=index, **kwargs)
|
3720
3831
|
|
3721
3832
|
wb = load_workbook(filename)
|
3722
|
-
|
3833
|
+
if isinstance(sheet_name, str):
|
3834
|
+
ws = wb[sheet_name]
|
3835
|
+
elif isinstance(sheet_name, int):
|
3836
|
+
ws = wb.worksheets[sheet_name]
|
3837
|
+
else:
|
3838
|
+
ws = wb.worksheets[sheet_name] # the index of worksheets
|
3723
3839
|
|
3724
3840
|
# !Apply cell formatting
|
3725
3841
|
if cell:
|
@@ -3812,7 +3928,9 @@ format_excel(
|
|
3812
3928
|
comment = [comment]
|
3813
3929
|
for comment_ in comment:
|
3814
3930
|
for (row, col), comment_str in comment_.items():
|
3815
|
-
ws.cell(row=row, column=col).comment = Comment(
|
3931
|
+
ws.cell(row=row + 1, column=col + 1).comment = Comment(
|
3932
|
+
comment_str, "Author"
|
3933
|
+
)
|
3816
3934
|
|
3817
3935
|
# !Add link
|
3818
3936
|
if link:
|
@@ -3820,7 +3938,7 @@ format_excel(
|
|
3820
3938
|
link = [link]
|
3821
3939
|
for link_ in link:
|
3822
3940
|
for (row, col), link_str in link_.items():
|
3823
|
-
ws.cell(row=row, column=col).hyperlink = link_str
|
3941
|
+
ws.cell(row=row + 1, column=col + 1).hyperlink = link_str
|
3824
3942
|
|
3825
3943
|
# !Apply data validation
|
3826
3944
|
if data_validation:
|
@@ -3870,3 +3988,52 @@ format_excel(
|
|
3870
3988
|
# Save the workbook
|
3871
3989
|
wb.save(filename)
|
3872
3990
|
print(f"Formatted Excel file saved as:\n{filename}")
|
3991
|
+
|
3992
|
+
|
3993
|
+
from IPython.display import display, HTML, Markdown, Image
|
3994
|
+
|
3995
|
+
def preview(var):
|
3996
|
+
"""Master function to preview formatted variables in Jupyter."""
|
3997
|
+
|
3998
|
+
if isinstance(var, str):
|
3999
|
+
if isa(var,'html'):
|
4000
|
+
display(HTML(var)) # Render as HTML
|
4001
|
+
# Check if it's a valid markdown
|
4002
|
+
elif var.startswith("#"):
|
4003
|
+
display(Markdown(var))
|
4004
|
+
else:
|
4005
|
+
# Otherwise, display as plain text
|
4006
|
+
print(var)
|
4007
|
+
|
4008
|
+
elif isinstance(var, pd.DataFrame):
|
4009
|
+
# Display pandas DataFrame
|
4010
|
+
display(var)
|
4011
|
+
|
4012
|
+
elif isinstance(var, list) or isinstance(var, dict):
|
4013
|
+
# Display JSON
|
4014
|
+
json_str = json.dumps(var, indent=4)
|
4015
|
+
display(Markdown(f"```json\n{json_str}\n```"))
|
4016
|
+
|
4017
|
+
elif isinstance(var, bytes):
|
4018
|
+
# Display image if it's in bytes format
|
4019
|
+
display(Image(data=var))
|
4020
|
+
|
4021
|
+
elif isinstance(var, str) and (var.endswith(".png") or var.endswith(".jpg")):
|
4022
|
+
# Display image from file path
|
4023
|
+
display(Image(filename=var))
|
4024
|
+
|
4025
|
+
elif isinstance(var, dict):
|
4026
|
+
# Handle dictionary formatting
|
4027
|
+
json_str = json.dumps(var, indent=4)
|
4028
|
+
display(Markdown(f"```json\n{json_str}\n```"))
|
4029
|
+
|
4030
|
+
else:
|
4031
|
+
# If the format is not recognized, print a message
|
4032
|
+
print("Format not recognized or unsupported.")
|
4033
|
+
|
4034
|
+
|
4035
|
+
# # Example usages:
|
4036
|
+
# preview("This is a plain text message.")
|
4037
|
+
# preview("# This is a Markdown header")
|
4038
|
+
# preview(pd.DataFrame({"Name": ["Alice", "Bob"], "Age": [25, 30]}))
|
4039
|
+
# preview({"key": "value", "numbers": [1, 2, 3]})
|
@@ -582,7 +582,7 @@ def find_links(url, driver="request", booster=False):
|
|
582
582
|
if all(exclusion not in link_href for exclusion in cond_ex):
|
583
583
|
links_href.append(link_href)
|
584
584
|
|
585
|
-
unique_links =
|
585
|
+
unique_links = ips.unique(links_href) # Remove duplicates
|
586
586
|
|
587
587
|
if booster:
|
588
588
|
for link in unique_links:
|
@@ -590,7 +590,7 @@ def find_links(url, driver="request", booster=False):
|
|
590
590
|
sub_links = find_links(link, driver=driver, booster=False)
|
591
591
|
if sub_links:
|
592
592
|
links_href.extend(sub_links)
|
593
|
-
links_href =
|
593
|
+
links_href = ips.unique(links_href) # Remove duplicates again
|
594
594
|
|
595
595
|
return links_href
|
596
596
|
|