diff --git a/README.md b/README.md
index 93e1e4c..f9d7acf 100644
--- a/README.md
+++ b/README.md
@@ -4,40 +4,39 @@
-
+
-
-
-
-
-
+
+
+
- pip-install-bitches was made by
+ pip-install-traps was made with
-Love β code β
+Cum β code β
---
-### πγ»Code example
-
-Example of how you can use [traps](https://pypi.org/project/traps/)
+### Installation
+```
+pip install -U traps
+```
+### Usage
```python
import traps
-traps.get()
-
-# or
-
-traps.get(
- "yes", # directory name (default: "traps")
- 5 # amount of traps (default: randint(5, 10))
-)
+traps.get() # Download to `traps` directory.
+traps.get("my_homework") # Or to another directory.
```
+
+### Command-line interface
+* `$ traps` to download 10 traps to `traps` directory
+* `$ traps -n 20 my_homework` to download 20 traps to `my_homework` directory
+* `$ traps --help` for more help
diff --git a/images/trap.jpg b/images/trap.jpg
new file mode 100644
index 0000000..942eab7
Binary files /dev/null and b/images/trap.jpg differ
diff --git a/poetry.lock b/poetry.lock
index 990c8c2..2d8273f 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -62,6 +62,21 @@ docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"]
perf = ["ipython"]
testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"]
+[[package]]
+name = "loguru"
+version = "0.6.0"
+description = "Python logging made (stupidly) simple"
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
+[package.dependencies]
+colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""}
+win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""}
+
+[package.extras]
+dev = ["colorama (>=0.3.4)", "docutils (==0.16)", "flake8 (>=3.7.7)", "tox (>=3.9.0)", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "black (>=19.10b0)", "isort (>=5.1.1)", "Sphinx (>=4.1.1)", "sphinx-autobuild (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)"]
+
[[package]]
name = "requests"
version = "2.28.0"
@@ -101,6 +116,17 @@ brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"]
secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
+[[package]]
+name = "win32-setctime"
+version = "1.1.0"
+description = "A small Python utility to set file creation time on Windows"
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
+[package.extras]
+dev = ["pytest (>=4.6.2)", "black (>=19.3b0)"]
+
[[package]]
name = "zipp"
version = "3.8.0"
@@ -116,7 +142,7 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-
[metadata]
lock-version = "1.1"
python-versions = "^3.7"
-content-hash = "1d7efb30a6917067ee323aff51674a885542ec0ab42d54f1b3a07ea5e0aac6e2"
+content-hash = "b10cf466f2fef3f183da66173a0f64e6aea107f54a3ab9c476c62548f3f798d0"
[metadata.files]
certifi = [
@@ -143,6 +169,10 @@ importlib-metadata = [
{file = "importlib_metadata-4.11.4-py3-none-any.whl", hash = "sha256:c58c8eb8a762858f49e18436ff552e83914778e50e9d2f1660535ffb364552ec"},
{file = "importlib_metadata-4.11.4.tar.gz", hash = "sha256:5d26852efe48c0a32b0509ffbc583fda1a2266545a78d104a6f4aff3db17d700"},
]
+loguru = [
+ {file = "loguru-0.6.0-py3-none-any.whl", hash = "sha256:4e2414d534a2ab57573365b3e6d0234dfb1d84b68b7f3b948e6fb743860a77c3"},
+ {file = "loguru-0.6.0.tar.gz", hash = "sha256:066bd06758d0a513e9836fd9c6b5a75bfb3fd36841f4b996bc60b547a309d41c"},
+]
requests = [
{file = "requests-2.28.0-py3-none-any.whl", hash = "sha256:bc7861137fbce630f17b03d3ad02ad0bf978c844f3536d0edda6499dafce2b6f"},
{file = "requests-2.28.0.tar.gz", hash = "sha256:d568723a7ebd25875d8d1eaf5dfa068cd2fc8194b2e483d7b1f7c81918dbec6b"},
@@ -155,6 +185,10 @@ urllib3 = [
{file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"},
{file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"},
]
+win32-setctime = [
+ {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"},
+ {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"},
+]
zipp = [
{file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"},
{file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"},
diff --git a/pyproject.toml b/pyproject.toml
index b26d7df..3cecc38 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -24,6 +24,7 @@ classifiers = [
python = "^3.7"
requests = "^2.28.0"
click = "^8.1.3"
+loguru = "^0.6.0"
[tool.poetry.dev-dependencies]
diff --git a/traps/__init__.py b/traps/__init__.py
index 38ddcf5..1c77c67 100644
--- a/traps/__init__.py
+++ b/traps/__init__.py
@@ -1,31 +1,50 @@
-import pathlib
+import os
import secrets
+import sys
+from typing import Union
import urllib.parse
-from multiprocessing import Pool
+from concurrent.futures import ThreadPoolExecutor
+from pathlib import Path
from threading import Thread
import click
import requests
+from loguru import logger
__version__ = "1.0.0"
API_URL = "https://api.waifu.pics/nsfw/trap"
+try:
+ logger.remove(0)
+except ValueError:
+ pass
-def get_traps(params):
- directory, url = params
- filename = urllib.parse.urlparse(url)
- filename = directory.joinpath(secrets.token_hex(8) + pathlib.Path(filename.path).suffix)
+
+def fetch_url(urls_list: list = None) -> str:
+ url = requests.get(API_URL).json()["url"]
+ if urls_list is not None:
+ urls_list.append(url)
+ return url
+
+
+def get(directory: Union[str, os.PathLike] = "traps", url: str = None,
+ create_dir: bool = True):
+ if url is None:
+ url = fetch_url()
+ directory = Path(directory)
+ if not directory.exists() and create_dir:
+ directory.mkdir()
+ filename = urllib.parse.urlparse(url).path
+ filename = directory.joinpath(secrets.token_hex(8) + Path(filename).suffix)
with open(filename, "wb") as f:
+ logger.debug(f"downloading {url}")
response = requests.get(url, stream=True)
for block in response.iter_content(1024):
if not block:
break
f.write(block)
-
-
-def fetch_url(urls_list: list):
- url = requests.get(API_URL).json()["url"]
- urls_list.append(url)
+ else:
+ logger.success(f"downloaded {url}")
@click.command(help="how about you pip install some traps")
@@ -38,33 +57,50 @@ def fetch_url(urls_list: list):
show_default=True,
help="number of traps to get"
)
+@click.option(
+ "-v",
+ "--verbose",
+ is_flag=True,
+ help="verbose output")
@click.argument(
"directory",
default="traps",
type=click.Path(
dir_okay=True,
file_okay=False,
- path_type=pathlib.Path
+ path_type=Path
)
)
-def main(traps: int, directory: pathlib.Path):
+def main(traps: int, directory: Path, verbose: bool):
+ if verbose:
+ loglevel = "DEBUG"
+ else:
+ loglevel = "INFO"
+ logger.add(
+ sys.stderr,
+ level=loglevel,
+ format="{time:YYYY-MM-DD HH:mm:ss} | "
+ "{level: <8} | {message}"
+ )
if not directory.exists():
+ logger.debug(f"creating directory {directory}")
directory.mkdir()
+ logger.debug("done")
urls = []
threads = [
Thread(target=fetch_url, args=(urls,))
for _ in range(traps)
]
+ logger.debug("fetching URLs")
for thread in threads:
thread.start()
for thread in threads:
thread.join()
- params = [
- (directory, url)
- for url in urls
- ]
- with Pool(8) as p:
- p.map(get_traps, params)
+ logger.debug("done")
+ logger.info("downloading traps")
+ with ThreadPoolExecutor(max_workers=8) as p:
+ p.map(lambda url: get(directory, url, False), urls)
+ logger.info(f"downloaded {traps} traps")
if __name__ == '__main__':