aria2py


Namearia2py JSON
Version 0.1.1 PyPI version JSON
download
home_pageNone
SummaryA modern, type-safe Python wrapper for aria2c with improved UX.
upload_time2025-10-10 09:43:58
maintainerNone
docs_urlNone
authorOmar Hanafy
requires_python>=3.9
licenseNone
keywords aria2 download bittorrent metalink rpc
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # aria2py

A modern, type-safe Python wrapper around the aria2c download utility with a clean local CLI experience and batteries-included JSON-RPC client.

## Requirements

- Python **3.9+**
- `aria2c` available on your `PATH`

Install aria2c first (examples show macOS and Debian/Ubuntu, adapt as needed):

```bash
# macOS
brew install aria2

# Debian/Ubuntu
sudo apt install aria2
```

## Installation

Install the latest release from PyPI:

```bash
pip install aria2py
```

To try the bleeding-edge version straight from GitHub:

```bash
pip install git+https://github.com/omar-hanafy/aria2py.git
```

## Quick Start

### One-liner download

```python
from aria2py import Aria2Client

client = Aria2Client()
result = client.download("https://example.com/file.zip")
print(result.stdout)
```

`download()` returns `subprocess.CompletedProcess`, so stdout/stderr and the exit code are readily available. Set `stream=True` to mirror aria2c’s live console output:

```python
client.download("https://example.com/file.zip", stream=True)
```

### Smart fetch helper

`fetch()` inspects the target and dispatches automatically:

```python
client.fetch("https://example.com/file.zip")    # HTTP/S
client.fetch("magnet:?xt=urn:btih:...")         # Magnet links
client.fetch("https://example.com/file.torrent")
client.fetch("downloads.meta4")
client.fetch(["https://mirror/a", "https://mirror/b"])  # Multiple URIs
```

If a local text file is passed, the path is emitted as `--input-file=...`.

### Configure options with dataclasses

Every aria2c switch maps to a typed field. Combine option groups to tailor the command:

```python
from aria2py import Aria2Client, BasicOptions, HttpOptions

client = Aria2Client(
    basic_options=BasicOptions(
        dir="/tmp/downloads",
        continue_download=True,
    ),
    http_options=HttpOptions(
        header=["User-Agent: aria2py"],
        retry_wait=5,
        max_tries=3,
    ),
)

client.fetch("https://example.com/bundle.zip")
```

Validation runs before any process is spawned, surfacing typos (bad enums, negative values, etc.) immediately.

### BitTorrent and Metalink helpers

```python
from aria2py import Aria2Client, BitTorrentOptions, MetalinkOptions

client = Aria2Client(
    bt_options=BitTorrentOptions(enable_dht=True, seed_ratio=1.0),
    metalink_options=MetalinkOptions(select_file="1-5", show_files=True),
)

client.download_magnet("magnet:?xt=urn:btih:...")
client.download_torrent("/path/to/file.torrent")
client.download_metalink("/path/to/file.meta4")
```

`MetalinkOptions` exposes dedicated `select_file` / `show_files` shims so you no longer need to reach into the BitTorrent option set for file selection.

## Working with the JSON-RPC API

### Starting and managing an RPC server

```python
from aria2py import Aria2Client, RpcOptions

client = Aria2Client(
    rpc_options=RpcOptions(
        enable_rpc=True,
        rpc_listen_port=6800,
        rpc_secret="my-secret-token",
    )
)

with client:  # starts aria2c with RPC enabled
    print(client.rpc.get_version())
    # ... perform RPC calls ...
```

The context manager ensures the aria2c process terminates cleanly when you exit the block. You can also call `start_rpc_server()` yourself; repeated calls are idempotent while the process is running.

To connect to an already running aria2c instance, disable the local binary requirement:

```python
remote = Aria2Client(
    rpc_options=RpcOptions(enable_rpc=True, rpc_listen_port=6800, rpc_secret="token"),
    require_local_binary=False,
)
print(remote.rpc.get_version())
```

### Queueing and controlling downloads

High-level helpers translate Python keyword arguments into aria2-compatible option dictionaries:

```python
from aria2py import Aria2Client, BasicOptions, RpcOptions

client = Aria2Client(
    basic_options=BasicOptions(dir="/data"),
    rpc_options=RpcOptions(enable_rpc=True, rpc_secret="token"),
    require_local_binary=False,
)

gid = client.add("https://example.com/archive.zip")
client.pause(gid)
client.resume(gid)
status = client.status(gid, keys=["status", "completedLength", "downloadSpeed"])
queue = client.waiting(offset=0, num=50)
stopped = client.stopped(offset=0, num=50)
stats = client.rpc.get_global_stat()

client.set_options(gid, max_download_limit="500K")
client.set_global(max_overall_download_limit="5M", enable_color=False)
```

Torrent and metalink payloads can be uploaded without manual base64 encoding:

```python
client.add_torrent_rpc("ubuntu.torrent", uris=["https://mirror.example/ubuntu.iso"])
client.add_metalink_rpc("downloads.meta4")
```

Errors coming back from aria2 are raised as `Aria2RpcError` so you can handle them cleanly:

```python
from aria2py.exceptions import Aria2RpcError

try:
    client.pause("0000000000000000")
except Aria2RpcError as exc:
    print(exc.code, exc)
```

If you need lower-level control, the underlying `Aria2RpcClient` is available via `client.rpc` and supports every helper directly (`add_uri`, `tell_active`, `remove_download_result`, `purge_download_result`, and more).

### Authenticating with cookies

aria2c understands the classic Netscape cookie jar format (the one Firefox/Chrome export). Point `HttpOptions.load_cookies` at your `cookies.txt` to replay authenticated sessions:

```python
from aria2py import Aria2Client, BasicOptions, HttpOptions

client = Aria2Client(
    basic_options=BasicOptions(dir="/tmp/downloads"),
    http_options=HttpOptions(
        load_cookies="/tmp/cookies.txt",          # use exported browser cookies
        save_cookies="/tmp/cookies-refreshed.txt" # optional: persist updates from aria2c
    ),
)

client.fetch("https://example.com/private/file.zip")
```

The same configuration flows through JSON-RPC calls (`add`, `add_torrent_rpc`, `set_options`, etc.), so downloads launched remotely pick up identical cookie headers. Paths must be accessible to the aria2c process, so prefer absolute locations.

## Streaming the aria2c console

When you pass `stream=True` to any download method (`download`, `download_magnet`, `fetch`, etc.) aria2py invokes aria2c with stdout/stderr wired to your terminal, mirroring the native CLI experience—handy when you want to monitor progress without parsing output.

## Error Handling

Custom exceptions provide actionable feedback:

- `Aria2NotInstalledError` – aria2c is missing on the host.
- `Aria2CommandError` – local process exited non-zero; includes stdout/stderr for debugging.
- `Aria2RpcError` – JSON-RPC error response with structured code/message/data attributes.

Example:

```python
from aria2py import Aria2Client, RpcOptions
from aria2py.exceptions import Aria2CommandError, Aria2NotInstalledError, Aria2RpcError

client = Aria2Client(require_local_binary=False, rpc_options=RpcOptions(enable_rpc=True))

try:
    client.fetch("https://example.com/file.zip")
except Aria2NotInstalledError:
    print("Install aria2c before running local downloads.")
except Aria2CommandError as exc:
    print(f"aria2c failed: {exc.stderr}")
except Aria2RpcError as exc:
    print(f"RPC error {exc.code}: {exc}")
```

## Testing

The repository ships with a growing unit test suite that exercises option conversion, dispatch logic, RPC payloads, and process lifecycle. Run everything with:

```bash
pytest
# or
python -m unittest discover
```

## Option Coverage

Option classes mirror the aria2 manual and are tracked in [docs/option_coverage.md](docs/option_coverage.md). Each dataclass groups related switches:

- `BasicOptions`
- `HttpOptions`
- `BitTorrentOptions`
- `MetalinkOptions`
- `RpcOptions`
- `AdvancedOptions`

Because the models are plain dataclasses, IDE auto-complete and static typing tools (mypy/pyright) work out of the box.

## License

aria2py is released under the MIT License. See [LICENSE](./LICENSE) for details.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "aria2py",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": "aria2, download, bittorrent, metalink, rpc",
    "author": "Omar Hanafy",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/6e/1e/bd3ce196f00c5cb1db5d83fc3e399322f89b8dab554927565bef1099a9e1/aria2py-0.1.1.tar.gz",
    "platform": null,
    "description": "# aria2py\n\nA modern, type-safe Python wrapper around the aria2c download utility with a clean local CLI experience and batteries-included JSON-RPC client.\n\n## Requirements\n\n- Python **3.9+**\n- `aria2c` available on your `PATH`\n\nInstall aria2c first (examples show macOS and Debian/Ubuntu, adapt as needed):\n\n```bash\n# macOS\nbrew install aria2\n\n# Debian/Ubuntu\nsudo apt install aria2\n```\n\n## Installation\n\nInstall the latest release from PyPI:\n\n```bash\npip install aria2py\n```\n\nTo try the bleeding-edge version straight from GitHub:\n\n```bash\npip install git+https://github.com/omar-hanafy/aria2py.git\n```\n\n## Quick Start\n\n### One-liner download\n\n```python\nfrom aria2py import Aria2Client\n\nclient = Aria2Client()\nresult = client.download(\"https://example.com/file.zip\")\nprint(result.stdout)\n```\n\n`download()` returns `subprocess.CompletedProcess`, so stdout/stderr and the exit code are readily available. Set `stream=True` to mirror aria2c\u2019s live console output:\n\n```python\nclient.download(\"https://example.com/file.zip\", stream=True)\n```\n\n### Smart fetch helper\n\n`fetch()` inspects the target and dispatches automatically:\n\n```python\nclient.fetch(\"https://example.com/file.zip\")    # HTTP/S\nclient.fetch(\"magnet:?xt=urn:btih:...\")         # Magnet links\nclient.fetch(\"https://example.com/file.torrent\")\nclient.fetch(\"downloads.meta4\")\nclient.fetch([\"https://mirror/a\", \"https://mirror/b\"])  # Multiple URIs\n```\n\nIf a local text file is passed, the path is emitted as `--input-file=...`.\n\n### Configure options with dataclasses\n\nEvery aria2c switch maps to a typed field. Combine option groups to tailor the command:\n\n```python\nfrom aria2py import Aria2Client, BasicOptions, HttpOptions\n\nclient = Aria2Client(\n    basic_options=BasicOptions(\n        dir=\"/tmp/downloads\",\n        continue_download=True,\n    ),\n    http_options=HttpOptions(\n        header=[\"User-Agent: aria2py\"],\n        retry_wait=5,\n        max_tries=3,\n    ),\n)\n\nclient.fetch(\"https://example.com/bundle.zip\")\n```\n\nValidation runs before any process is spawned, surfacing typos (bad enums, negative values, etc.) immediately.\n\n### BitTorrent and Metalink helpers\n\n```python\nfrom aria2py import Aria2Client, BitTorrentOptions, MetalinkOptions\n\nclient = Aria2Client(\n    bt_options=BitTorrentOptions(enable_dht=True, seed_ratio=1.0),\n    metalink_options=MetalinkOptions(select_file=\"1-5\", show_files=True),\n)\n\nclient.download_magnet(\"magnet:?xt=urn:btih:...\")\nclient.download_torrent(\"/path/to/file.torrent\")\nclient.download_metalink(\"/path/to/file.meta4\")\n```\n\n`MetalinkOptions` exposes dedicated `select_file` / `show_files` shims so you no longer need to reach into the BitTorrent option set for file selection.\n\n## Working with the JSON-RPC API\n\n### Starting and managing an RPC server\n\n```python\nfrom aria2py import Aria2Client, RpcOptions\n\nclient = Aria2Client(\n    rpc_options=RpcOptions(\n        enable_rpc=True,\n        rpc_listen_port=6800,\n        rpc_secret=\"my-secret-token\",\n    )\n)\n\nwith client:  # starts aria2c with RPC enabled\n    print(client.rpc.get_version())\n    # ... perform RPC calls ...\n```\n\nThe context manager ensures the aria2c process terminates cleanly when you exit the block. You can also call `start_rpc_server()` yourself; repeated calls are idempotent while the process is running.\n\nTo connect to an already running aria2c instance, disable the local binary requirement:\n\n```python\nremote = Aria2Client(\n    rpc_options=RpcOptions(enable_rpc=True, rpc_listen_port=6800, rpc_secret=\"token\"),\n    require_local_binary=False,\n)\nprint(remote.rpc.get_version())\n```\n\n### Queueing and controlling downloads\n\nHigh-level helpers translate Python keyword arguments into aria2-compatible option dictionaries:\n\n```python\nfrom aria2py import Aria2Client, BasicOptions, RpcOptions\n\nclient = Aria2Client(\n    basic_options=BasicOptions(dir=\"/data\"),\n    rpc_options=RpcOptions(enable_rpc=True, rpc_secret=\"token\"),\n    require_local_binary=False,\n)\n\ngid = client.add(\"https://example.com/archive.zip\")\nclient.pause(gid)\nclient.resume(gid)\nstatus = client.status(gid, keys=[\"status\", \"completedLength\", \"downloadSpeed\"])\nqueue = client.waiting(offset=0, num=50)\nstopped = client.stopped(offset=0, num=50)\nstats = client.rpc.get_global_stat()\n\nclient.set_options(gid, max_download_limit=\"500K\")\nclient.set_global(max_overall_download_limit=\"5M\", enable_color=False)\n```\n\nTorrent and metalink payloads can be uploaded without manual base64 encoding:\n\n```python\nclient.add_torrent_rpc(\"ubuntu.torrent\", uris=[\"https://mirror.example/ubuntu.iso\"])\nclient.add_metalink_rpc(\"downloads.meta4\")\n```\n\nErrors coming back from aria2 are raised as `Aria2RpcError` so you can handle them cleanly:\n\n```python\nfrom aria2py.exceptions import Aria2RpcError\n\ntry:\n    client.pause(\"0000000000000000\")\nexcept Aria2RpcError as exc:\n    print(exc.code, exc)\n```\n\nIf you need lower-level control, the underlying `Aria2RpcClient` is available via `client.rpc` and supports every helper directly (`add_uri`, `tell_active`, `remove_download_result`, `purge_download_result`, and more).\n\n### Authenticating with cookies\n\naria2c understands the classic Netscape cookie jar format (the one Firefox/Chrome export). Point `HttpOptions.load_cookies` at your `cookies.txt` to replay authenticated sessions:\n\n```python\nfrom aria2py import Aria2Client, BasicOptions, HttpOptions\n\nclient = Aria2Client(\n    basic_options=BasicOptions(dir=\"/tmp/downloads\"),\n    http_options=HttpOptions(\n        load_cookies=\"/tmp/cookies.txt\",          # use exported browser cookies\n        save_cookies=\"/tmp/cookies-refreshed.txt\" # optional: persist updates from aria2c\n    ),\n)\n\nclient.fetch(\"https://example.com/private/file.zip\")\n```\n\nThe same configuration flows through JSON-RPC calls (`add`, `add_torrent_rpc`, `set_options`, etc.), so downloads launched remotely pick up identical cookie headers. Paths must be accessible to the aria2c process, so prefer absolute locations.\n\n## Streaming the aria2c console\n\nWhen you pass `stream=True` to any download method (`download`, `download_magnet`, `fetch`, etc.) aria2py invokes aria2c with stdout/stderr wired to your terminal, mirroring the native CLI experience\u2014handy when you want to monitor progress without parsing output.\n\n## Error Handling\n\nCustom exceptions provide actionable feedback:\n\n- `Aria2NotInstalledError` \u2013 aria2c is missing on the host.\n- `Aria2CommandError` \u2013 local process exited non-zero; includes stdout/stderr for debugging.\n- `Aria2RpcError` \u2013 JSON-RPC error response with structured code/message/data attributes.\n\nExample:\n\n```python\nfrom aria2py import Aria2Client, RpcOptions\nfrom aria2py.exceptions import Aria2CommandError, Aria2NotInstalledError, Aria2RpcError\n\nclient = Aria2Client(require_local_binary=False, rpc_options=RpcOptions(enable_rpc=True))\n\ntry:\n    client.fetch(\"https://example.com/file.zip\")\nexcept Aria2NotInstalledError:\n    print(\"Install aria2c before running local downloads.\")\nexcept Aria2CommandError as exc:\n    print(f\"aria2c failed: {exc.stderr}\")\nexcept Aria2RpcError as exc:\n    print(f\"RPC error {exc.code}: {exc}\")\n```\n\n## Testing\n\nThe repository ships with a growing unit test suite that exercises option conversion, dispatch logic, RPC payloads, and process lifecycle. Run everything with:\n\n```bash\npytest\n# or\npython -m unittest discover\n```\n\n## Option Coverage\n\nOption classes mirror the aria2 manual and are tracked in [docs/option_coverage.md](docs/option_coverage.md). Each dataclass groups related switches:\n\n- `BasicOptions`\n- `HttpOptions`\n- `BitTorrentOptions`\n- `MetalinkOptions`\n- `RpcOptions`\n- `AdvancedOptions`\n\nBecause the models are plain dataclasses, IDE auto-complete and static typing tools (mypy/pyright) work out of the box.\n\n## License\n\naria2py is released under the MIT License. See [LICENSE](./LICENSE) for details.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "A modern, type-safe Python wrapper for aria2c with improved UX.",
    "version": "0.1.1",
    "project_urls": {
        "Bug Tracker": "https://github.com/omar-hanafy/aria2py/issues",
        "Homepage": "https://github.com/omar-hanafy/aria2py"
    },
    "split_keywords": [
        "aria2",
        " download",
        " bittorrent",
        " metalink",
        " rpc"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "580038b37e81d2030a9a9405b7ac2d121b42f6816f6b547a273184381e435853",
                "md5": "f0146c427e3d3ab8234f22190bc54a30",
                "sha256": "2916444eb9fb89642595a7af90f5d0c59a80584811a08512298f2e78b2223553"
            },
            "downloads": -1,
            "filename": "aria2py-0.1.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "f0146c427e3d3ab8234f22190bc54a30",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 18472,
            "upload_time": "2025-10-10T09:43:57",
            "upload_time_iso_8601": "2025-10-10T09:43:57.342700Z",
            "url": "https://files.pythonhosted.org/packages/58/00/38b37e81d2030a9a9405b7ac2d121b42f6816f6b547a273184381e435853/aria2py-0.1.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "6e1ebd3ce196f00c5cb1db5d83fc3e399322f89b8dab554927565bef1099a9e1",
                "md5": "de9bbc83a47fe2bc9e6858e67562ed25",
                "sha256": "bc9e332541bfef3dfdcc0ceb4c350abf866dcd476323a38888b29821ae8ce974"
            },
            "downloads": -1,
            "filename": "aria2py-0.1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "de9bbc83a47fe2bc9e6858e67562ed25",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 22229,
            "upload_time": "2025-10-10T09:43:58",
            "upload_time_iso_8601": "2025-10-10T09:43:58.682579Z",
            "url": "https://files.pythonhosted.org/packages/6e/1e/bd3ce196f00c5cb1db5d83fc3e399322f89b8dab554927565bef1099a9e1/aria2py-0.1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-10 09:43:58",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "omar-hanafy",
    "github_project": "aria2py",
    "github_not_found": true,
    "lcname": "aria2py"
}
        
Elapsed time: 0.92023s