py2ls 0.2.4.34__tar.gz → 0.2.4.35__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.2.4.34 → py2ls-0.2.4.35}/PKG-INFO +6 -2
- py2ls-0.2.4.35/py2ls/data/RealESRGAN_x4plus.pth +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/ips.py +350 -33
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/netfinder.py +30 -40
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/ocr.py +2 -2
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/pyproject.toml +6 -2
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/README.md +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.DS_Store +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/.DS_Store +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/COMMIT_EDITMSG +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/FETCH_HEAD +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/HEAD +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/config +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/description +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/hooks/applypatch-msg.sample +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/hooks/commit-msg.sample +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/hooks/fsmonitor-watchman.sample +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/hooks/post-update.sample +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/hooks/pre-applypatch.sample +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/hooks/pre-commit.sample +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/hooks/pre-merge-commit.sample +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/hooks/pre-push.sample +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/hooks/pre-rebase.sample +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/hooks/pre-receive.sample +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/hooks/prepare-commit-msg.sample +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/hooks/push-to-checkout.sample +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/hooks/update.sample +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/index +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/info/exclude +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/logs/HEAD +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/logs/refs/heads/main +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/logs/refs/remotes/origin/HEAD +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/logs/refs/remotes/origin/main +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/.DS_Store +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/01/d5bd8065e6860c0bd23ff9fa57161806a099e1 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/09/08da26de58c114225ad81f484b80bf5d351b34 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/0b/409e1bc918277010f5679b402d1d1dda53e15c +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/12/c2808a1b3a4d0892a4154dfba1e2ae3770fa73 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/14/449a0e6ba4ea2f1a73acf63ef91c9c6193f9ed +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/15/a8e468aacfcb440e090020f36d0b985d45da23 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/1a/b4585881a6a42889f01aa0cfe25fd5acfaf46f +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/1c/3f92adda34344bcbbbf9d409c79855ae2aaea8 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/1c/9314c5f69b9390068a2a8616875d974849d71f +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/1d/fe9d9633b24ea560354f4f93d39c6e5f163ea0 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/20/72c28e83f4347959d29f7b3a6c1fc3e4ee6b59 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/24/6b368b986f758630c46dc02b7fa512b53422f7 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/25/b796accd261b9135fd32a2c00785f68edf6c46 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/27/aa6074f652bc6f7078f8647489d9ee8e24f0e2 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/28/c2969d785c1b892c2a96b3f00eba63a59811b3 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/2a/ae95d517d213b660bf4f65a4e0cfae7bb893eb +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/2a/fdf45791a26d42ccead35ace76a8f0b2a56561 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/30/a2f8da47ee947811dc8d993f5a06a45de374f4 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/32/fd627b62fad7cf3b2f9e34ab9777126a0987ad +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/34/9e31b6a3634cea102ce5588b98c11cc1738605 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/34/b6f3a2ee84f39bed4eee57f2c0e0afb994feb1 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/35/1a5f491ab97eee9d1ee699478d75a8bb5d3dc2 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/36/b4a1b7403abc6c360f8fe2cb656ab945254971 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/36/e56a361f526eafa59c5235a5c990bf288b5f9c +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/36/ef43e50009e59db11812c258846d9e38718173 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/39/7ead045fbbcfb17c62019eb18fe21ed05dbee5 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/39/b13be65125556784e44c7a1d9821703c7ab67e +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/3b/507acc7f23391644cc0b824b1e79fd2677a362 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/3b/bd972aa7ad680858f8dfbd0f7fcd97756f0d6f +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/3c/bbe5f4173d165127b9ad96119f1ec24c306ffc +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/3d/9d10d27724657a436c65a6254bfd213d4b3562 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/3f/d6561300938afbb3d11976cf9c8f29549280d9 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/41/dcf4b3bf0460946b2da93776cf9e836d62178f +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/43/dbd49b2ee367c5434dd545e3b5795434f2ef0b +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/45/b1b6178bacbfc997811a998b5cc60c1ea7fac8 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/47/6cbd5a7c5e35cddef2f8a38bdc4896d403b095 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/48/a88fc5806305d0bb0755ee6801161b79696972 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/4f/7afb40dff2153d857fc85748c2eecb85125042 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/50/08ddfcf53c02e82d7eee2e57c38e5672ef89f6 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/53/e0deb1cb4c2c606bced6e7f9a66b0fda60980d +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/56/e4e8b2d5545e0256090f45aa8fc42c5fe067d0 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/57/63d0c52f5c9c69e89d514a1f96034947abe21a +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/57/bd1c0199483ab316235b094543b85edec6c35e +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/58/20a729045d4dc7e37ccaf8aa8eec126850afe2 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/59/380c4c26bdcd4d9b71ae3e2e35f05b3f26c5ab +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/5a/192565abf89c9d765af846ce6d53a92b1ce7ad +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/60/f273eb1c412d916fa3f11318a7da7a9911b52a +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/61/570cec8c061abe74121f27f5face6c69b98f99 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/62/4488173ed2c8936fa5cea3cf5dd3f26a30b86e +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/62/7c81b23b4e56e87b042b650b0103653cc9e34a +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/62/d90ccf8cbefdc2e4fd475e7c6f4f76e9fdf801 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/63/100154b27846e8010e55b6bf4b3d7762c14c5f +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/64/27a4edff08f93d98f511418423f09f2ab90bcd +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/66/6227eeeba24073e63811e89f1449f3d958f183 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/66/c998778721d424bd0aae80602dabbffa93af2e +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/68/6df3072c8b025fb18106ed2df505994ad062a9 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/69/13c452ca319f7cbf6a0836dc10a5bb033c84e4 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/6a/52e747a2b349b128d1490d9e896d2323818eb7 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/6b/7fde264d93a7a0986d394c46c7650d0ce2ab92 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/6c/cebb29b7f3f5b0c889f6dadbf9ff066554587d +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/6d/c2cdf4a84e538e5d4777486aeff87e42f41799 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/6d/ee29dbdcc84edeeacede105110446f3ccac963 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/71/36b2074a2754be8b58127d82250e5b37e3c373 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/72/245a05b0966011cb381e6b32b0465000e969ab +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/72/e4179337639859678ddaecf38b16f33aaec8e1 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/78/063f4c863fc371ec0313303c0a81283b35d9b6 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/78/3d4167bc95c9d2175e0df03ef1c1c880ba75ab +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/79/7ae089b2212a937840e215276005ce76881307 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/7e/5956c806b5edc344d46dab599dec337891ba1f +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/81/8f26b7bf042269729020cf944fc362d66ba27e +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/82/70b319ce4046854fbe7dc41054b6c2d112dab2 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/84/59071b722a255b774a80b27746033f8141ab39 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/85/aee46f478e9afdb84d50a05242c53b04ed2e21 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/86/e288b46f8fe179907e4413f665aeb5053fddb1 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/87/ef1fc3f7f1ddc4d0ab9b3e65381ce9f3388621 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/8b/84f56978e1de8f2ae82abce5f8b3e182d365cd +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/8e/55a7d2b96184030211f20c9b9af201eefcac82 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/91/c69ad88fe0ba94aa7859fb5f7edac5e6f1a3f7 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/94/74152b4b463d70ae5ad07f0c658be3e296026b +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/94/f7dbe88e80c4205a901b71eb8f181974376bba +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/97/1aef09ea939f46b60b9646f8d524c78a9220f4 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/9b/ec5ee2236ee2d5532c36bfd132e23c58fdb69c +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/9d/0df52899fe95279059286d9c0ec42287edc168 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/a1/5389729850729fc7bd78a54f26fce77f30be12 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/a1/906da89d1174f74867800c74c43af36253bd5e +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/a4/63fdd23e5efd713db8a71f316f3a1c7bd60916 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/a5/ec8f74642fbba27f7ea78c53b372ae0c7dedce +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/a7/3e13eafee65c5b8d73ad2d3ea46d0eee82f0d3 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/b0/56be4be89ba6b76949dd641df45bb7036050c8 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/b0/9cd7856d58590578ee1a4f3ad45d1310a97f87 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/b2/18e6a0f0f1c4df8cdefa9852058348abc713b7 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/b3/4f7f271c6d6105e35a6556ffda71d03afe8c96 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/b3/69579064bde9de9a19d114fc33e4e48cc8c0e4 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/b5/61831c7dce8ea51e7ee6b6fa35745f14d8242d +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/b7/2c9e75ab7d0afe594664650aa8f6c772f5ac64 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/bb/81ccc0513f18fc160b54a82861e9a80d23f4f6 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/bb/934eb33bc1a8b85630bf680caffd99560c1b8f +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/bf/67907e337021ebff434e02b19b30a741c144af +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/bf/b54d65922ce1dfda1aaa014913a54e7172d0bc +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/c1/20fc812b9ad311c34a3608512d6a9d976bb48e +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/c1/397c6ed72c4e20ef6b9ab83163e9a6baba5b45 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/c4/cba65f1163661999ee4b8ed23342b63bc1300c +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/c6/7f17e5707313600efcb85e9a3fedea35dba591 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/c6/f32aced880bd165a251cb52b26b0c1107e2141 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/cc/45df1d317a2eb63ff1ff3a5f3b4a9f98fd92b5 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/cd/822b3574a88ebdd1ed82fd6983f37e626d52b4 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/cf/0c0d9c6fb09473aaeb7f7e2edbd770c3f2ef3d +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/d2/992df305f4b56a466a2f221aeb182ddd20f418 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/d6/39e8af592cd75a318d8affddd1bcc70c2095f2 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/d6/9ab1c4aadf279936dd778e8346ba60f74705b6 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/d8/4688b54c0040a30976b3a6540bc47adf7ce680 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/d9/005f2cc7fc4e65f14ed5518276007c08cf2fd0 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/d9/c2403fd166ce791b4e9d0c6792ed8342c71fcd +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/d9/dfa5aee51e92a541b707e8e7baea6f06deff98 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/db/141dbaa93594df2a8156182f361ee4db829359 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/db/3f2cd643292057936230b95cf7ec3046affe11 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/db/ffa8ea7bda721d0cee7b9e4ce5b2ef927733ff +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/dc/c2bdbafb3296e09d9ee4955cfa55d275825f94 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/dc/cdbd4266765d840be2ae35ab1752a0fa312c16 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/dd/87fb5f606fe380d81e6fe3a2c98f9f99e3e09b +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/de/214c626ac2dd2685bfaa0bc0fc20f528d014d7 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/df/e0770424b2a19faf507a501ebfc23be8f54e7b +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/e2/f2f8f4c25e62a297fc55f36acc6b01cfbab76f +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/e3/1356f90ea6dd0577b5e0b40b206319adcbf085 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/e3/5a4dafc50850cacac7bf76c56db2715cbda2c4 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/e4/6c715352db9fe3c887a635f1916df4ca1f4ff9 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/e5/0580a0bd1e1b3d29f834382b80fceb61d5cf0c +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/e9/391ffe371f1cc43b42ef09b705d9c767c2e14f +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/ea/3a18cc75e53792744ef754e05d3f4481768c13 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/ec/40fd8bf8e4c342534a9fc020289e402ba6bc9d +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/ec/d980279432b13f0374b90ca439a6329cdece0f +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/ee/cee64eacaff022dcdc509c0c2b1da492f21060 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/f1/e50757fddc28b445545dc7e2759b54cdd0f42e +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/f4/b64d3107b39e3ad6f540c6607004ea34e6c024 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/f4/ba7f815b886797b73fede071d86e0c134d2bc7 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/f5/61c3c1bf1c9ea9c9d1f556a7be2869f71f3bdf +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/f6/44a8ff56fa035105fc517cbb1ac46c3d8e349a +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/f7/c98ba5c2f903e603b1f5e63d49fbc8a43815cc +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/f9/045a08e96eb76848fc4d68e3e3e687cca39a2d +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/fa/147e6bb78a2e8db241d231295fd7f1ed061af8 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/objects/fc/292e793ecfd42240ac43be407023bd731fa9e7 +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/refs/.DS_Store +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/refs/heads/main +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/refs/remotes/origin/HEAD +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.git/refs/remotes/origin/main +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.gitattributes +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/.gitignore +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/LICENSE +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/README.md +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/__init__.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/batman.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/bio.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/brain_atlas.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/chat.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/corr.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/correlators.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/.DS_Store +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/db2ls_sql_chtsht.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/docs_links.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/email/email_html_template.html +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/hyper_param_autogluon_zeroshot2024.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/hyper_param_tabrepo_2024.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/lang_code_iso639.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/mygenes_fields_241022.txt +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/sns_info.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/.DS_Store +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/example/.DS_Store +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/example/style1.pdf +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/example/style2.pdf +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/example/style3.pdf +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/example/style4.pdf +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/example/style5.pdf +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/example/style6.pdf +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/example/style7.pdf +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/example/style8.pdf +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/example/style9.pdf +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/style1.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/style10.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/style11.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/style12.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/style2.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/style3.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/style4.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/style5.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/style6.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/style7.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/style8.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/style9.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/.DS_Store +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/grid.mplstyle +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/high-contrast.mplstyle +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/high-vis.mplstyle +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/ieee.mplstyle +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/light.mplstyl +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/muted.mplstyle +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/nature-reviews-latex.mplstyle +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/nature-reviews.mplstyle +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/nature.mplstyle +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/no-latex.mplstyle +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/notebook.mplstyle +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/paper.mplstyle +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/retro.mplstyle +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/sans.mplstyle +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/scatter.mplstyle +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/science.mplstyle +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/std-colors.mplstyle +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/styles/stylelib/vibrant.mplstyle +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/tiles.csv +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/usages_pd.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/data/usages_sns.json +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/db2ls.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/doc.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/ec2ls.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/export_requirements.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/fetch_update.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/freqanalysis.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/ich2ls.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/ml2ls.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/mol.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/nl2ls.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/plot.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/setuptools-70.1.0-py3-none-any.whl +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/sleep_events_detectors.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/stats.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/translator.py +0 -0
- {py2ls-0.2.4.34 → py2ls-0.2.4.35}/py2ls/wb_detector.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: py2ls
|
3
|
-
Version: 0.2.4.
|
3
|
+
Version: 0.2.4.35
|
4
4
|
Summary: py(thon)2(too)ls
|
5
5
|
Author: Jianfeng
|
6
6
|
Author-email: Jianfeng.Liu0413@gmail.com
|
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.10
|
15
15
|
Classifier: Programming Language :: Python :: 3.11
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
17
|
-
Provides-Extra:
|
17
|
+
Provides-Extra: full
|
18
18
|
Requires-Dist: CacheControl (>=0.13.1)
|
19
19
|
Requires-Dist: Cython (>=3.0.10)
|
20
20
|
Requires-Dist: Deprecated (>=1.2.14)
|
@@ -123,6 +123,7 @@ Requires-Dist: mne (>=1.7.1)
|
|
123
123
|
Requires-Dist: more-itertools (>=10.3.0)
|
124
124
|
Requires-Dist: mpmath (>=1.3.0)
|
125
125
|
Requires-Dist: msgpack (>=1.0.8)
|
126
|
+
Requires-Dist: msoffcrypto-tool (>=5.4.2)
|
126
127
|
Requires-Dist: mtscomp (>=1.0.2)
|
127
128
|
Requires-Dist: nbclient (>=0.10.0)
|
128
129
|
Requires-Dist: nbconvert (>=7.16.4)
|
@@ -131,6 +132,7 @@ Requires-Dist: neo (>=0.13.1)
|
|
131
132
|
Requires-Dist: nest-asyncio (>=1.6.0)
|
132
133
|
Requires-Dist: networkx (>=3.3)
|
133
134
|
Requires-Dist: nltk (>=3.8.1)
|
135
|
+
Requires-Dist: nuitka (>=2.5.9)
|
134
136
|
Requires-Dist: numba (>=0.59.1)
|
135
137
|
Requires-Dist: numcodecs (>=0.13.0)
|
136
138
|
Requires-Dist: numerizer (>=0.2.3)
|
@@ -139,6 +141,7 @@ Requires-Dist: onnxruntime (>=1.18.1)
|
|
139
141
|
Requires-Dist: opencv-contrib-python (>=4.10.0.84)
|
140
142
|
Requires-Dist: opencv-python (>=4.10.0.84)
|
141
143
|
Requires-Dist: opencv-python-headless (>=4.10.0.84)
|
144
|
+
Requires-Dist: openpyxl (>=3.1.5)
|
142
145
|
Requires-Dist: outcome (>=1.3.0.post0)
|
143
146
|
Requires-Dist: packaging (>=24.1)
|
144
147
|
Requires-Dist: pandas (>=2.2.2)
|
@@ -199,6 +202,7 @@ Requires-Dist: rpds-py (>=0.18.1)
|
|
199
202
|
Requires-Dist: scikit-image (>=0.23.2)
|
200
203
|
Requires-Dist: scikit-learn (>=1.5.1)
|
201
204
|
Requires-Dist: scipy (>=1.14.0)
|
205
|
+
Requires-Dist: scrapy (>=2.12.0)
|
202
206
|
Requires-Dist: seaborn (>=0.13.2)
|
203
207
|
Requires-Dist: selenium (>=4.23.1)
|
204
208
|
Requires-Dist: setuptools (>=70.3.0)
|
Binary file
|
@@ -32,10 +32,16 @@ def backup(
|
|
32
32
|
tar="/Users/macjianfeng/Dropbox/github/python/py2ls/py2ls/",
|
33
33
|
kind="py",
|
34
34
|
overwrite=True,
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
35
|
+
reverse=False,
|
36
|
+
verbose=False
|
37
|
+
):
|
38
|
+
if reverse:
|
39
|
+
src, tar = tar,src
|
40
|
+
print(f"reversed")
|
41
|
+
f = listdir(src, kind, verbose=verbose)
|
42
|
+
[copy(i, tar, overwrite=overwrite, verbose=verbose) for i in f.path]
|
43
|
+
print(f"all files are copied from {os.path.basename(src)} to {tar}") if verbose else None
|
44
|
+
|
39
45
|
def run_once_within(duration=60, reverse=False): # default 60s
|
40
46
|
import time
|
41
47
|
|
@@ -2693,13 +2699,41 @@ def fload(fpath, kind=None, **kwargs):
|
|
2693
2699
|
def load_excel(fpath, **kwargs):
|
2694
2700
|
engine = kwargs.get("engine", "openpyxl")
|
2695
2701
|
verbose = kwargs.pop("verbose", False)
|
2696
|
-
|
2697
|
-
|
2698
|
-
|
2702
|
+
password=kwargs.pop("password",None)
|
2703
|
+
|
2704
|
+
if not password:
|
2705
|
+
if run_once_within(reverse=True):
|
2706
|
+
use_pd("read_excel", verbose=verbose)
|
2707
|
+
df = pd.read_excel(fpath, engine=engine, **kwargs)
|
2708
|
+
try:
|
2709
|
+
meta = pd.ExcelFile(fpath)
|
2710
|
+
print(f"n_sheet={len(meta.sheet_names)},\t'sheetname = 0 (default)':")
|
2711
|
+
[print(f"{i}:\t{i_}") for i, i_ in enumerate(meta.sheet_names)]
|
2712
|
+
except:
|
2713
|
+
pass
|
2714
|
+
return df
|
2715
|
+
#* needs a password?
|
2716
|
+
import msoffcrypto # pip install msoffcrypto-tool
|
2717
|
+
from io import BytesIO
|
2718
|
+
|
2719
|
+
# Open the encrypted Excel file
|
2720
|
+
with open(fpath, 'rb') as f:
|
2721
|
+
try:
|
2722
|
+
office_file = msoffcrypto.OfficeFile(f)
|
2723
|
+
office_file.load_key(password=password) # Provide the password
|
2724
|
+
decrypted = BytesIO()
|
2725
|
+
office_file.decrypt(decrypted)
|
2726
|
+
except:
|
2727
|
+
office_file = msoffcrypto.OfficeFile(f)
|
2728
|
+
office_file.load_key(password=depass(password)) # Provide the password
|
2729
|
+
decrypted = BytesIO()
|
2730
|
+
office_file.decrypt(decrypted)
|
2731
|
+
decrypted.seek(0)
|
2732
|
+
df = pd.read_excel(decrypted, engine=engine, **kwargs)
|
2699
2733
|
try:
|
2700
|
-
|
2701
|
-
print(f"n_sheet={len(
|
2702
|
-
[print(f"{i}:\t{i_}") for i, i_ in enumerate(
|
2734
|
+
meta = pd.ExcelFile(fpath)
|
2735
|
+
print(f"n_sheet={len(meta.sheet_names)},\t'sheetname = 0 (default)':")
|
2736
|
+
[print(f"{i}:\t{i_}") for i, i_ in enumerate(meta.sheet_names)]
|
2703
2737
|
except:
|
2704
2738
|
pass
|
2705
2739
|
return df
|
@@ -3283,11 +3317,16 @@ def fsave(
|
|
3283
3317
|
df = pd.DataFrame(data)
|
3284
3318
|
df.to_csv(fpath, **kwargs_valid)
|
3285
3319
|
|
3286
|
-
|
3320
|
+
|
3321
|
+
def save_xlsx(fpath, data, password=None, **kwargs):
|
3322
|
+
import msoffcrypto
|
3323
|
+
from io import BytesIO
|
3287
3324
|
verbose = kwargs.pop("verbose", False)
|
3288
3325
|
sheet_name = kwargs.pop("sheet_name", "Sheet1")
|
3326
|
+
|
3289
3327
|
if run_once_within(reverse=True):
|
3290
3328
|
use_pd("to_excel", verbose=verbose)
|
3329
|
+
|
3291
3330
|
if any(kwargs):
|
3292
3331
|
format_excel(df=data, filename=fpath, **kwargs)
|
3293
3332
|
else:
|
@@ -3312,16 +3351,30 @@ def fsave(
|
|
3312
3351
|
kwargs.pop(key, None)
|
3313
3352
|
|
3314
3353
|
df = pd.DataFrame(data)
|
3315
|
-
|
3316
|
-
|
3317
|
-
|
3318
|
-
|
3319
|
-
|
3320
|
-
|
3321
|
-
|
3322
|
-
|
3323
|
-
|
3324
|
-
|
3354
|
+
|
3355
|
+
# Write to Excel without password first
|
3356
|
+
temp_file = BytesIO()
|
3357
|
+
df.to_excel(temp_file, sheet_name=sheet_name, index=False, engine="xlsxwriter", **kwargs)
|
3358
|
+
|
3359
|
+
# If a password is provided, encrypt the file
|
3360
|
+
if password:
|
3361
|
+
temp_file.seek(0)
|
3362
|
+
office_file = msoffcrypto.OfficeFile(temp_file)
|
3363
|
+
office_file.load_key(password=password) # Provide the password
|
3364
|
+
|
3365
|
+
# Encrypt and save the file
|
3366
|
+
with open(fpath, 'wb') as encrypted_file:
|
3367
|
+
office_file.encrypt(encrypted_file)
|
3368
|
+
else:
|
3369
|
+
# Save the file without encryption if no password is provided
|
3370
|
+
try:
|
3371
|
+
# Use ExcelWriter with append mode if the file exists
|
3372
|
+
with pd.ExcelWriter(fpath, engine="openpyxl", mode="a", if_sheet_exists="new") as writer:
|
3373
|
+
df.to_excel(writer, sheet_name=sheet_name, index=False, **kwargs)
|
3374
|
+
except FileNotFoundError:
|
3375
|
+
# If file doesn't exist, create a new one
|
3376
|
+
df.to_excel(fpath, sheet_name=sheet_name, index=False, **kwargs)
|
3377
|
+
|
3325
3378
|
|
3326
3379
|
def save_ipynb(fpath, data, **kwargs):
|
3327
3380
|
# Split the content by code fences to distinguish between code and markdown
|
@@ -4410,13 +4463,13 @@ def func_list(lib_name, opt="call"):
|
|
4410
4463
|
return list_func(lib_name, opt=opt)
|
4411
4464
|
|
4412
4465
|
|
4413
|
-
def copy(src, dst, overwrite=False):
|
4466
|
+
def copy(src, dst, overwrite=False, verbose=True):
|
4414
4467
|
"""Copy a file from src to dst."""
|
4415
4468
|
try:
|
4416
4469
|
dir_par_dst = os.path.dirname(dst)
|
4417
4470
|
if not os.path.isdir(dir_par_dst):
|
4418
4471
|
mkdir(dir_par_dst)
|
4419
|
-
print(dir_par_dst)
|
4472
|
+
print(dir_par_dst) if verbose else None
|
4420
4473
|
src = Path(src)
|
4421
4474
|
dst = Path(dst)
|
4422
4475
|
if not src.is_dir():
|
@@ -4431,7 +4484,7 @@ def copy(src, dst, overwrite=False):
|
|
4431
4484
|
f"{dst.stem}_{datetime.now().strftime('_%H%M%S')}{dst.suffix}"
|
4432
4485
|
)
|
4433
4486
|
shutil.copy(src, dst)
|
4434
|
-
print(f"\n Done! copy to {dst}\n")
|
4487
|
+
print(f"\n Done! copy to {dst}\n") if verbose else None
|
4435
4488
|
else:
|
4436
4489
|
dst = dst / src.name
|
4437
4490
|
if dst.exists():
|
@@ -4442,7 +4495,7 @@ def copy(src, dst, overwrite=False):
|
|
4442
4495
|
f"{dst.stem}_{datetime.now().strftime('%H%M%S')}"
|
4443
4496
|
)
|
4444
4497
|
shutil.copytree(src, dst)
|
4445
|
-
print(f"\n Done! copy to {dst}\n")
|
4498
|
+
print(f"\n Done! copy to {dst}\n") if verbose else None
|
4446
4499
|
|
4447
4500
|
except Exception as e:
|
4448
4501
|
logging.error(f"Failed {e}")
|
@@ -4452,7 +4505,7 @@ def cut(src, dst, overwrite=False):
|
|
4452
4505
|
return move(src=src, dst=dst, overwrite=overwrite)
|
4453
4506
|
|
4454
4507
|
|
4455
|
-
def move(src, dst, overwrite=False):
|
4508
|
+
def move(src, dst, overwrite=False, verbose=True):
|
4456
4509
|
try:
|
4457
4510
|
dir_par_dst = os.path.dirname(dst)
|
4458
4511
|
if not os.path.isdir(dir_par_dst):
|
@@ -4470,7 +4523,7 @@ def move(src, dst, overwrite=False):
|
|
4470
4523
|
f"{dst.stem}_{datetime.now().strftime('_%H%M%S')}{dst.suffix}"
|
4471
4524
|
)
|
4472
4525
|
shutil.move(src, dst)
|
4473
|
-
print(f"\n Done! moved to {dst}\n")
|
4526
|
+
print(f"\n Done! moved to {dst}\n") if verbose else None
|
4474
4527
|
except Exception as e:
|
4475
4528
|
logging.error(f"Failed to move file from {src} to {dst}: {e}")
|
4476
4529
|
|
@@ -4729,6 +4782,19 @@ def figsave(*args, dpi=300):
|
|
4729
4782
|
plt.savefig(fname, format="emf", dpi=dpi, bbox_inches="tight", pad_inches=0)
|
4730
4783
|
elif ftype.lower() == "fig":
|
4731
4784
|
plt.savefig(fname, format="pdf", bbox_inches="tight", dpi=dpi, pad_inches=0)
|
4785
|
+
|
4786
|
+
elif ftype.lower() == "ico":
|
4787
|
+
# Ensure the image is in a format that can be saved as an icon (e.g., 32x32, 64x64, etc.)
|
4788
|
+
if img is None: # If no image is provided, use the matplotlib figure
|
4789
|
+
img = plt.figure()
|
4790
|
+
img.savefig(fname, dpi=dpi, format="png", bbox_inches="tight")
|
4791
|
+
img = Image.open(fname) # Load the saved figure image
|
4792
|
+
|
4793
|
+
# Resize the image to typical icon sizes and save it as .ico
|
4794
|
+
icon_sizes = [(32, 32), (64, 64), (128, 128), (256, 256)]
|
4795
|
+
img = img.convert("RGBA") # Ensure it has an alpha channel for transparency
|
4796
|
+
img.save(fname, format="ICO", sizes=icon_sizes)
|
4797
|
+
print(f"Icon saved @: {fname} with sizes: {icon_sizes}")
|
4732
4798
|
print(f"\nSaved @: dpi={dpi}\n{fname}")
|
4733
4799
|
|
4734
4800
|
|
@@ -5507,7 +5573,6 @@ def detect_angle(image, by="median", template=None):
|
|
5507
5573
|
print(f"Unknown method {by}: supported methods: {methods}")
|
5508
5574
|
return 0
|
5509
5575
|
|
5510
|
-
|
5511
5576
|
def imgsets(img,
|
5512
5577
|
auto:bool=True,
|
5513
5578
|
size=None,
|
@@ -5594,7 +5659,6 @@ def imgsets(img,
|
|
5594
5659
|
"birefnet-massive": "A pre-trained model with massive dataset.",
|
5595
5660
|
}
|
5596
5661
|
models_support_rem=list(rem_models.keys())
|
5597
|
-
|
5598
5662
|
str_usage="""
|
5599
5663
|
imgsets(dir_img, auto=1, color=1.5, plot_=0)
|
5600
5664
|
imgsets(dir_img, color=2)
|
@@ -5714,7 +5778,7 @@ def imgsets(img,
|
|
5714
5778
|
kwargs = {**auto_enhance(img_update), **kwargs}
|
5715
5779
|
params=["sharp","color","contrast","bright","crop","rotate",'size',"resize",
|
5716
5780
|
"thumbnail","cover","contain","filter","fit","pad",
|
5717
|
-
"rem","rm","back","bg_color","cut",
|
5781
|
+
"rem","rm","back","bg_color","cut","gamma","flip","booster"]
|
5718
5782
|
for k, value in kwargs.items():
|
5719
5783
|
k = strcmp(k, params)[0] # correct the param name
|
5720
5784
|
if "shar" in k.lower():
|
@@ -5735,7 +5799,7 @@ def imgsets(img,
|
|
5735
5799
|
img_update = ImageOps.autocontrast(img_update)
|
5736
5800
|
print("autocontrasted")
|
5737
5801
|
except Exception as e:
|
5738
|
-
print(f"Failed '
|
5802
|
+
print(f"Failed 'auto-contrasted':{e}")
|
5739
5803
|
elif "bri" in k.lower():
|
5740
5804
|
enhancer = ImageEnhance.Brightness(img_update)
|
5741
5805
|
img_update = enhancer.enhance(value)
|
@@ -5780,9 +5844,12 @@ def imgsets(img,
|
|
5780
5844
|
from rembg import remove, new_session
|
5781
5845
|
if verbose:
|
5782
5846
|
preview(rem_models)
|
5847
|
+
|
5848
|
+
print(f"supported modles: {models_support_rem}")
|
5783
5849
|
model=strcmp(model, models_support_rem)[0]
|
5784
5850
|
session = new_session(model)
|
5785
5851
|
if isinstance(value, bool):
|
5852
|
+
print(f"using model:{model}")
|
5786
5853
|
img_update = remove(img_update, session=session)
|
5787
5854
|
elif value and isinstance(value, (int, float, list)):
|
5788
5855
|
if verbose:
|
@@ -5817,6 +5884,7 @@ def imgsets(img,
|
|
5817
5884
|
img_update = remove(img_update, bgcolor=value, session=session)
|
5818
5885
|
elif isinstance(value, str):
|
5819
5886
|
# use custom model
|
5887
|
+
print(f"using model:{strcmp(value, models_support_rem)[0]}")
|
5820
5888
|
img_update = remove(img_update, session=new_session(strcmp(value, models_support_rem)[0]))
|
5821
5889
|
elif "bg" in k.lower() and "color" in k.lower():
|
5822
5890
|
from rembg import remove
|
@@ -5827,7 +5895,33 @@ def imgsets(img,
|
|
5827
5895
|
if len(value) == 3:
|
5828
5896
|
value += (255,)
|
5829
5897
|
img_update = remove(img_update, bgcolor=value)
|
5830
|
-
|
5898
|
+
elif 'boost' in k.lower():
|
5899
|
+
import torch
|
5900
|
+
from realesrgan import RealESRGANer
|
5901
|
+
if verbose:
|
5902
|
+
print("Applying Real-ESRGAN for image reconstruction...")
|
5903
|
+
if isinstance(value, bool):
|
5904
|
+
scale=4
|
5905
|
+
elif isinstance(value, (float, int)):
|
5906
|
+
scale=value
|
5907
|
+
else:
|
5908
|
+
scale=4
|
5909
|
+
|
5910
|
+
# try:
|
5911
|
+
device = "cuda" if torch.cuda.is_available() else "cpu"
|
5912
|
+
dir_curr_script = os.path.dirname(os.path.abspath(__file__))
|
5913
|
+
model_path = dir_curr_script + "/data/RealESRGAN_x4plus.pth"
|
5914
|
+
model_RealESRGAN = RealESRGANer(device=device,
|
5915
|
+
scale=scale,
|
5916
|
+
model_path=model_path,
|
5917
|
+
model="RealESRGAN_x4plus"
|
5918
|
+
)
|
5919
|
+
# https://github.com/xinntao/Real-ESRGAN?tab=readme-ov-file#python-script
|
5920
|
+
|
5921
|
+
img_update = model_RealESRGAN.enhance(np.array(img_update))[0]
|
5922
|
+
# except Exception as e:
|
5923
|
+
# print(f"Failed to apply Real-ESRGAN: {e}")
|
5924
|
+
|
5831
5925
|
# elif "ga" in k.lower() and "m" in k.lower():
|
5832
5926
|
# img_update = gamma_correction(img_update, gamma=value)
|
5833
5927
|
# Display the image if requested
|
@@ -10728,4 +10822,227 @@ def mouse(
|
|
10728
10822
|
# "Image not found. Ensure the image is visible and parameters are correct."
|
10729
10823
|
# )
|
10730
10824
|
# except Exception as e:
|
10731
|
-
# print(f"An error occurred: {e}")
|
10825
|
+
# print(f"An error occurred: {e}")
|
10826
|
+
|
10827
|
+
|
10828
|
+
|
10829
|
+
def py2installer(
|
10830
|
+
script_path: str=None,
|
10831
|
+
flatform:str="mingw64",
|
10832
|
+
output_dir: str = "dist",
|
10833
|
+
icon_path: str = None,
|
10834
|
+
extra_data: list = None,
|
10835
|
+
hidden_imports: list = None,
|
10836
|
+
plugins:list=None,
|
10837
|
+
use_nuitka: bool = True,
|
10838
|
+
onefile: bool = True,
|
10839
|
+
console: bool = True,
|
10840
|
+
clean_build: bool = False,
|
10841
|
+
additional_args: list = None,
|
10842
|
+
verbose: bool = True,
|
10843
|
+
use_docker: bool = False,
|
10844
|
+
docker_image: str = "python:3.12-slim",
|
10845
|
+
):
|
10846
|
+
"""
|
10847
|
+
to package Python scripts into standalone application.
|
10848
|
+
|
10849
|
+
script_path (str): Path to the Python script to package.
|
10850
|
+
output_dir (str): Directory where the executable will be stored.
|
10851
|
+
icon_path (str): Path to the .ico file for the executable icon.
|
10852
|
+
extra_data (list): List of additional data files or directories in "source:dest" format.
|
10853
|
+
hidden_imports (list): List of hidden imports to include.
|
10854
|
+
plugins (list): List of plugins imports to include.e.g., 'tk-inter'
|
10855
|
+
use_nuitka (bool): Whether to use Nuitka instead of PyInstaller.
|
10856
|
+
onefile (bool): If True, produces a single executable file.
|
10857
|
+
console (bool): If False, hides the console window (GUI mode).
|
10858
|
+
clean_build (bool): If True, cleans previous build and dist directories.
|
10859
|
+
additional_args (list): Additional arguments for PyInstaller/Nuitka.
|
10860
|
+
verbose (bool): If True, provides detailed logs.
|
10861
|
+
use_docker (bool): If True, uses Docker to package the script.
|
10862
|
+
docker_image (str): Docker image to use for packaging.
|
10863
|
+
|
10864
|
+
"""
|
10865
|
+
|
10866
|
+
import os
|
10867
|
+
import sys
|
10868
|
+
import shutil
|
10869
|
+
import subprocess
|
10870
|
+
import sys
|
10871
|
+
import glob
|
10872
|
+
from pathlib import Path
|
10873
|
+
if run_once_within():
|
10874
|
+
usage_str="""
|
10875
|
+
# build locally
|
10876
|
+
py2installer(
|
10877
|
+
script_path="update_tab.py",
|
10878
|
+
output_dir="dist",
|
10879
|
+
icon_path="icon4app.ico",
|
10880
|
+
extra_data=["dat/*.xlsx:dat"],
|
10881
|
+
hidden_imports=["msoffcrypto", "tkinter", "pandas", "numpy"],
|
10882
|
+
onefile=True,
|
10883
|
+
console=False,
|
10884
|
+
clean_build=True,
|
10885
|
+
verbose=True,
|
10886
|
+
)
|
10887
|
+
# build via docker
|
10888
|
+
py2installer(
|
10889
|
+
"my_script.py",
|
10890
|
+
output_dir="dist",
|
10891
|
+
onefile=True,
|
10892
|
+
clean_build=True,
|
10893
|
+
use_docker=True,
|
10894
|
+
docker_image="python:3.12-slim"
|
10895
|
+
)
|
10896
|
+
"""
|
10897
|
+
print(usage_str)
|
10898
|
+
if verbose:
|
10899
|
+
return
|
10900
|
+
else:
|
10901
|
+
pass
|
10902
|
+
# Check if the script path exists
|
10903
|
+
script_path = Path(script_path)
|
10904
|
+
if not script_path.exists():
|
10905
|
+
raise FileNotFoundError(f"Script '{script_path}' not found.")
|
10906
|
+
|
10907
|
+
# Clean build and dist directories if requested
|
10908
|
+
if clean_build:
|
10909
|
+
for folder in ["build", "dist"]:
|
10910
|
+
folder_path = Path(folder)
|
10911
|
+
if folder_path.exists():
|
10912
|
+
shutil.rmtree(folder_path, ignore_errors=True)
|
10913
|
+
# Recreate the folders
|
10914
|
+
for folder in ["build", "dist"]:
|
10915
|
+
folder_path = Path(folder)
|
10916
|
+
folder_path.mkdir(parents=True, exist_ok=True)
|
10917
|
+
|
10918
|
+
|
10919
|
+
if use_docker:
|
10920
|
+
# Ensure Docker is installed
|
10921
|
+
try:
|
10922
|
+
subprocess.run(["docker", "--version"], check=True, capture_output=True, text=True)
|
10923
|
+
except FileNotFoundError:
|
10924
|
+
raise EnvironmentError("Docker is not installed or not in the PATH.")
|
10925
|
+
|
10926
|
+
# Prepare Docker volume mappings
|
10927
|
+
script_dir = script_path.parent.resolve()
|
10928
|
+
dist_path = Path(output_dir).resolve()
|
10929
|
+
volumes = [
|
10930
|
+
f"{script_dir}:/app:rw",
|
10931
|
+
f"{dist_path}:/output:rw",
|
10932
|
+
]
|
10933
|
+
docker_cmd = [
|
10934
|
+
"docker", "run", "--rm",
|
10935
|
+
"-v", volumes[0],
|
10936
|
+
"-v", volumes[1],
|
10937
|
+
docker_image,
|
10938
|
+
"bash", "-c",
|
10939
|
+
]
|
10940
|
+
|
10941
|
+
# Build the packaging command inside the container
|
10942
|
+
cmd = ["nuitka"] if use_nuitka else ["pyinstaller"]
|
10943
|
+
if onefile:
|
10944
|
+
cmd.append("--onefile")
|
10945
|
+
if not console:
|
10946
|
+
cmd.append("--windowed")
|
10947
|
+
cmd.extend(["--distpath", "/output"])
|
10948
|
+
if icon_path:
|
10949
|
+
cmd.extend(["--icon", f"/app/{Path(icon_path).name}"])
|
10950
|
+
if extra_data:
|
10951
|
+
for data in extra_data:
|
10952
|
+
cmd.extend(["--add-data", f"/app/{data}"])
|
10953
|
+
if hidden_imports:
|
10954
|
+
for hidden in hidden_imports:
|
10955
|
+
cmd.extend(["--hidden-import", hidden])
|
10956
|
+
if additional_args:
|
10957
|
+
cmd.extend(additional_args)
|
10958
|
+
cmd.append(f"/app/{script_path.name}")
|
10959
|
+
|
10960
|
+
# Full command to execute inside the container
|
10961
|
+
docker_cmd.append(" ".join(cmd))
|
10962
|
+
|
10963
|
+
if verbose:
|
10964
|
+
print(f"Running Docker command: {' '.join(docker_cmd)}")
|
10965
|
+
|
10966
|
+
# Run Docker command
|
10967
|
+
try:
|
10968
|
+
subprocess.run(
|
10969
|
+
docker_cmd,
|
10970
|
+
capture_output=not verbose,
|
10971
|
+
text=True,
|
10972
|
+
check=True,
|
10973
|
+
)
|
10974
|
+
except subprocess.CalledProcessError as e:
|
10975
|
+
print(f"Error during Docker packaging:\n{e.stderr}", file=sys.stderr)
|
10976
|
+
raise
|
10977
|
+
else:
|
10978
|
+
# Handle local packaging (native build)
|
10979
|
+
cmd = ["nuitka"]
|
10980
|
+
cmd.append("--standalone") # Make sure to use --standalone for independent environments
|
10981
|
+
if 'min' in flatform.lower():
|
10982
|
+
cmd.append("--mingw64")
|
10983
|
+
if onefile:
|
10984
|
+
cmd.append("--onefile")
|
10985
|
+
if not console:
|
10986
|
+
# cmd.append("--windows-disable-console") # Disabled based on your request
|
10987
|
+
pass
|
10988
|
+
|
10989
|
+
cmd.extend([f"--output-dir={output_dir}"]) # Correct the space issue here
|
10990
|
+
if icon_path:
|
10991
|
+
icon_path = Path(icon_path)
|
10992
|
+
if not icon_path.exists():
|
10993
|
+
raise FileNotFoundError(f"Icon file '{icon_path}' not found.")
|
10994
|
+
cmd.extend([f"--windows-icon-from-ico={icon_path}"])
|
10995
|
+
|
10996
|
+
if extra_data:
|
10997
|
+
for data in extra_data:
|
10998
|
+
if "*" in data:
|
10999
|
+
matches = glob.glob(data.split(":")[0])
|
11000
|
+
for match in matches:
|
11001
|
+
dest = data.split(":")[1]
|
11002
|
+
cmd.extend(
|
11003
|
+
[
|
11004
|
+
"--include-data-file=" if use_nuitka else "--add-data",
|
11005
|
+
f"{match}:{dest}",
|
11006
|
+
]
|
11007
|
+
)
|
11008
|
+
else:
|
11009
|
+
cmd.extend(
|
11010
|
+
["--include-data-file=" if use_nuitka else "--add-data", data]
|
11011
|
+
)
|
11012
|
+
|
11013
|
+
if hidden_imports:
|
11014
|
+
cmd.extend([f"--nofollow-import-to={','.join(hidden_imports)}"])
|
11015
|
+
|
11016
|
+
if plugins:
|
11017
|
+
for plugin in plugins:
|
11018
|
+
cmd.extend([f"--plugin-enable={plugin}"])
|
11019
|
+
|
11020
|
+
if additional_args:
|
11021
|
+
cmd.extend(additional_args)
|
11022
|
+
|
11023
|
+
# Add the script path (final positional argument)
|
11024
|
+
cmd.append(str(script_path))
|
11025
|
+
|
11026
|
+
# Ensure Windows shell compatibility
|
11027
|
+
shell_flag = sys.platform.startswith("win")
|
11028
|
+
|
11029
|
+
# Run the command
|
11030
|
+
if verbose:
|
11031
|
+
print(f"Running command: {' '.join(cmd)}")
|
11032
|
+
try:
|
11033
|
+
result = subprocess.run(
|
11034
|
+
cmd,
|
11035
|
+
capture_output=not verbose,
|
11036
|
+
text=True,
|
11037
|
+
shell=shell_flag,
|
11038
|
+
check=True,
|
11039
|
+
)
|
11040
|
+
if verbose:
|
11041
|
+
print(result.stdout)
|
11042
|
+
except subprocess.CalledProcessError as e:
|
11043
|
+
print(f"Error during packaging:\n{e.stderr}", file=sys.stderr)
|
11044
|
+
print(" ".join(cmd))
|
11045
|
+
raise
|
11046
|
+
|
11047
|
+
print("\nPackaging complete. Check the output directory for the executable.")
|
11048
|
+
|
@@ -333,32 +333,6 @@ def parse_cookies(cookies_str):
|
|
333
333
|
|
334
334
|
return cookies_dict
|
335
335
|
|
336
|
-
class FetchSpider(scrapy.Spider):
|
337
|
-
name = "fetch_spider"
|
338
|
-
|
339
|
-
def __init__(self, url, parser="html.parser", cookies=None, headers=None, *args, **kwargs):
|
340
|
-
super(FetchSpider, self).__init__(*args, **kwargs)
|
341
|
-
self.start_urls = [url]
|
342
|
-
self.cookies = cookies
|
343
|
-
self.headers = headers
|
344
|
-
self.parser = parser
|
345
|
-
|
346
|
-
def start_requests(self):
|
347
|
-
for url in self.start_urls:
|
348
|
-
yield scrapy.Request(
|
349
|
-
url,
|
350
|
-
cookies=self.cookies,
|
351
|
-
headers=self.headers,
|
352
|
-
callback=self.parse
|
353
|
-
)
|
354
|
-
|
355
|
-
def parse(self, response):
|
356
|
-
# Use the desired parser (default: html.parser)
|
357
|
-
from bs4 import BeautifulSoup
|
358
|
-
soup = BeautifulSoup(response.text, self.parser)
|
359
|
-
yield {"content": soup}
|
360
|
-
|
361
|
-
|
362
336
|
def fetch_scrapy(
|
363
337
|
url,
|
364
338
|
parser="html.parser",
|
@@ -367,7 +341,7 @@ def fetch_scrapy(
|
|
367
341
|
settings=None,
|
368
342
|
):
|
369
343
|
"""
|
370
|
-
Fetches content using Scrapy.
|
344
|
+
Fetches content using Scrapy with proper reactor handling.
|
371
345
|
|
372
346
|
Args:
|
373
347
|
url (str): The URL to scrape.
|
@@ -380,9 +354,10 @@ def fetch_scrapy(
|
|
380
354
|
dict: Parsed content as a dictionary.
|
381
355
|
"""
|
382
356
|
from scrapy.utils.project import get_project_settings
|
383
|
-
from scrapy.crawler import
|
357
|
+
from scrapy.crawler import CrawlerRunner
|
384
358
|
from scrapy.signalmanager import dispatcher
|
385
359
|
from scrapy import signals
|
360
|
+
from twisted.internet import reactor, defer
|
386
361
|
import scrapy
|
387
362
|
|
388
363
|
# Container for scraped content
|
@@ -403,19 +378,30 @@ def fetch_scrapy(
|
|
403
378
|
}
|
404
379
|
)
|
405
380
|
|
406
|
-
#
|
407
|
-
process = CrawlerProcess(settings=process_settings)
|
381
|
+
# Connect item scraped signal
|
408
382
|
dispatcher.connect(handle_item, signal=signals.item_scraped)
|
409
383
|
|
410
|
-
#
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
384
|
+
# Asynchronous Twisted function
|
385
|
+
@defer.inlineCallbacks
|
386
|
+
def crawl():
|
387
|
+
runner = CrawlerRunner(settings=process_settings)
|
388
|
+
yield runner.crawl(
|
389
|
+
FetchSpider,
|
390
|
+
url=url,
|
391
|
+
parser=parser,
|
392
|
+
cookies=cookies,
|
393
|
+
headers=headers,
|
394
|
+
)
|
395
|
+
reactor.stop()
|
396
|
+
|
397
|
+
# Start the reactor if not already running
|
398
|
+
if not reactor.running:
|
399
|
+
crawl()
|
400
|
+
reactor.run() # Blocks until the crawl finishes
|
401
|
+
else:
|
402
|
+
# Run the crawl if the reactor is already running
|
403
|
+
d = crawl()
|
404
|
+
d.addBoth(lambda _: reactor.stop())
|
419
405
|
|
420
406
|
# Return the first scraped content or None if empty
|
421
407
|
return content[0] if content else None
|
@@ -654,7 +640,11 @@ def fetch_all(
|
|
654
640
|
"COOKIES_ENABLED": True if cookies else False,
|
655
641
|
"LOG_LEVEL": "WARNING", # Reduce log verbosity
|
656
642
|
}
|
657
|
-
content=fetch_scrapy(url,
|
643
|
+
content=fetch_scrapy(url,
|
644
|
+
parser=parser,
|
645
|
+
cookies=cookies,
|
646
|
+
headers=headers,
|
647
|
+
settings=settings)
|
658
648
|
return parser, content
|
659
649
|
|
660
650
|
except requests.RequestException as e:
|
@@ -561,8 +561,8 @@ def get_text(
|
|
561
561
|
font=cv2.FONT_HERSHEY_SIMPLEX,# draw_box
|
562
562
|
fontsize=8,# draw_box
|
563
563
|
figsize=[10,10],
|
564
|
-
box_color = (0, 255, 0),
|
565
|
-
fontcolor = (
|
564
|
+
box_color = (0, 255, 0), # draw_box
|
565
|
+
fontcolor = (116,173,233), # draw_box
|
566
566
|
bg_color=(133, 203, 245, 100),# draw_box
|
567
567
|
usage=False,
|
568
568
|
**kwargs,
|