Skip to content

Commit

Permalink
feat: use asyncio (#106)
Browse files Browse the repository at this point in the history
* feat: use `asyncio`
* feat: replace `requests` with `httpx`
* feat: bump minimal `python` version to `3.9`
* feat: replace `kdialog` with `notify-send`, make optional
* feat: remove hosting `pictshare` (discontinued)
* test: increase coverage
  • Loading branch information
DeadNews authored Jun 22, 2023
1 parent 40898e2 commit d6966de
Show file tree
Hide file tree
Showing 15 changed files with 537 additions and 420 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.8", "3.9", "3.10", "3.11"]
python-version: ["3.9", "3.10", "3.11"]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion PKGBUILD
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ depends=(
"python"
"python-click"
"python-dotenv"
"python-httpx"
"python-pillow"
"python-pyperclip"
"python-requests"
)
makedepends=(
"python-build"
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ yay -S python-images-upload-cli
| [imgchest](https://imgchest.com/) | + | `https://cdn.imgchest.com/files/{id}.png` |
| [imgur](https://imgur.com/) | - | `https://i.imgur.com/{id}.png` |
| [lensdump](https://lensdump.com/) | + | `https://i.lensdump.com/i/{id}.png` |
| [pictshare](https://pictshare.net/) | - | `https://pictshare.net/{id}.png` |
| [pixeldrain](https://pixeldrain.com/) | - | `https://pixeldrain.com/api/file/{id}` |
| [pixhost](https://pixhost.to/) | - | `https://img75.pixhost.to/images/69/{id}_img.png` |
| [ptpimg](https://ptpimg.me/) | + | `https://ptpimg.me/{id}.png` |
Expand All @@ -62,10 +61,12 @@ Usage: images-upload-cli [OPTIONS] IMAGES...
Upload images via APIs.

Options:
-h, --hosting [beeimg|catbox|fastpic|filecoffee|freeimage|gyazo|imageban|imagebin|imgbb|imgchest|imgur|lensdump|pictshare|pixeldrain|pixhost|ptpimg|smms|sxcu|telegraph|thumbsnap|tixte|up2sha|uplio|uploadcare|vgy]
-h, --hosting [beeimg|catbox|fastpic|filecoffee|freeimage|gyazo|imageban|imagebin|imgbb|imgchest|imgur|lensdump|pixeldrain|pixhost|ptpimg|smms|sxcu|telegraph|thumbsnap|tixte|up2sha|uplio|uploadcare|vgy]
[default: imgur]
-b, --bbcode Add bbcode tags.
-t, --thumbnail Add caption thumbnail and bbcode tags.
-n, --notify / -N, --no-notify Send desktop notifications via libnotify.
[default: N]
-c, --clipboard / -C, --no-clipboard
Copy result to clipboard. [default: c]
--version Show the version and exit.
Expand Down
431 changes: 209 additions & 222 deletions poetry.lock

Large diffs are not rendered by default.

23 changes: 12 additions & 11 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,24 @@ classifiers = ["Environment :: Console", "Operating System :: OS Independent"]
images-upload-cli = "images_upload_cli.cli:cli"

[tool.poetry.dependencies]
python = "^3.8.1"
python = "^3.9"
click = "^8.1.3"
httpx = "^0.24.1"
pillow = "^9.5.0"
pyperclip = "^1.8.2"
python-dotenv = "^1.0.0"
requests = "^2.30.0"

[tool.poetry.group.lint.dependencies]
black = "^23.3.0"
mypy = "^1.4.0"
poethepoet = "^0.20.0"
ruff = "^0.0.275"
types-requests = "^2.29.0.0"

[tool.poetry.group.test.dependencies]
pytest = "^7.3.2"
pytest-cov = "^4.1.0"
pytest-asyncio = "^0.21.0"
pytest-httpx = "^0.22.0"

[tool.poe.tasks]
ruff = "ruff check ."
Expand Down Expand Up @@ -74,15 +75,15 @@ exclude_lines = ["if TYPE_CHECKING:", "if __name__ == .__main__.:"]
line-length = 99
select = ["ALL"]
ignore = [
"COM812", # Trailing comma missing
"D203", # 1 blank line required before class docstring
"D212", # Multi-line docstring summary should start at the first line
"E501", # Line too long
"EXE001", # Shebang is present but file is not executable
"FBT001", # Boolean positional arg in function definition
"FBT002", # Boolean default value in function definition
"COM812", # Trailing comma missing
"D203", # 1 blank line required before class docstring
"D212", # Multi-line docstring summary should start at the first line
"E501", # Line too long
"EXE001", # Shebang is present but file is not executable
"FBT001", # Boolean positional arg in function definition
"FBT002", # Boolean default value in function definition
"PLR0913", # Too many arguments to function call
#
"S113", # Missing requests timeout
"S603", # Calling subprocess.Popen with shell=False
]

Expand Down
2 changes: 1 addition & 1 deletion src/images_upload_cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python
"""Public accessible objects of that module."""

from images_upload_cli.upload import HOSTINGS, UPLOAD, UploadError
from images_upload_cli.upload import HOSTINGS, UPLOAD
from images_upload_cli.util import make_thumbnail
66 changes: 48 additions & 18 deletions src/images_upload_cli/cli.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
#!/usr/bin/env python
"""Entrypoint for cli."""
from __future__ import annotations

import asyncio
from collections.abc import Callable
from pathlib import Path

import click
from dotenv import load_dotenv
from httpx import AsyncClient
from pyperclip import copy

from images_upload_cli.upload import HOSTINGS, UPLOAD
from images_upload_cli.util import get_config_path, kdialog, make_thumbnail
from images_upload_cli.util import get_config_path, make_thumbnail, notify_send


@click.command(context_settings={"show_default": True})
Expand All @@ -22,6 +24,13 @@
@click.option("-h", "--hosting", type=click.Choice(HOSTINGS), default="imgur")
@click.option("-b", "--bbcode", is_flag=True, help="Add bbcode tags.")
@click.option("-t", "--thumbnail", is_flag=True, help="Add caption thumbnail and bbcode tags.")
@click.option(
"-n/-N",
"--notify/--no-notify",
is_flag=True,
default=False,
help="Send desktop notifications via libnotify.",
)
@click.option(
"-c/-C",
"--clipboard/--no-clipboard",
Expand All @@ -35,31 +44,52 @@ def cli(
hosting: str,
bbcode: bool,
thumbnail: bool,
notify: bool,
clipboard: bool,
) -> None:
"""Upload images via APIs."""
# loading .env variables
load_dotenv(dotenv_path=get_config_path())

# get upload func
upload_func = UPLOAD[hosting]

# image upload
links = []
for img_path in images:
img = img_path.read_bytes()

if not thumbnail:
link = f"[img]{upload_func(img)}[/img]" if bbcode else upload_func(img)
else:
thumb = make_thumbnail(img)
link = f"[url={upload_func(img)}][img]{upload_func(thumb)}[/img][/url]"

links.append(link)
# async images upload
links = asyncio.run(
upload_images(
upload_func=UPLOAD[hosting],
images=images,
bbcode=bbcode,
thumbnail=thumbnail,
)
)

# out
links_str = " ".join(links)
click.echo(links_str)
if clipboard:
copy(links_str)
kdialog(links_str)
if notify:
notify_send(links_str)


async def upload_images(
upload_func: Callable,
images: tuple[Path],
bbcode: bool,
thumbnail: bool,
) -> list[str]:
"""Upload images coroutine."""
links = []

async with AsyncClient() as client:
for img_path in images:
img = img_path.read_bytes()

img_link = await upload_func(client, img)
if not thumbnail:
link = f"[img]{img_link}[/img]" if bbcode else img_link
else:
thumb_link = await upload_func(client, make_thumbnail(img))
link = f"[url={img_link}][img]{thumb_link}[/img][/url]"

links.append(link)

return links
Loading

0 comments on commit d6966de

Please sign in to comment.