Skip to content

Commit

Permalink
feat!: redesign core API (#6)
Browse files Browse the repository at this point in the history
BREAKING CHANGE
  • Loading branch information
Ravencentric authored Feb 1, 2025
1 parent a34b451 commit fcde6f5
Show file tree
Hide file tree
Showing 32 changed files with 1,870 additions and 995 deletions.
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
groups:
actions:
patterns:
- "*"
9 changes: 3 additions & 6 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,9 @@ jobs:
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
- name: Install uv
id: setup-uv
uses: astral-sh/setup-uv@v3

- name: Install the project
run: uv sync --all-extras --python 3.12
- uses: astral-sh/setup-uv@v5
with:
python-version: "3.13"

- name: Deploy docs
run: uv run mkdocs gh-deploy --force
9 changes: 3 additions & 6 deletions .github/workflows/lint-and-type-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,9 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Install uv
id: setup-uv
uses: astral-sh/setup-uv@v3

- name: Install the project
run: uv sync --all-extras --python 3.12
- uses: astral-sh/setup-uv@v5
with:
python-version: "3.13"

- name: Run mypy
run: uv run mypy .
Expand Down
17 changes: 4 additions & 13 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,13 @@ jobs:
with:
fetch-depth: 0 # Important for changelog

- name: Install uv
id: setup-uv
uses: astral-sh/setup-uv@v3

- name: Install Python 3.12
run: uv python install 3.12
- uses: astral-sh/setup-uv@v5
with:
python-version: "3.13"

- name: Build
run: uv build

- uses: actions/attest-build-provenance@v1
with:
subject-path: "dist/*"

- name: Generate changelog with git-cliff
uses: tj-actions/git-cliff@v1
with:
Expand All @@ -46,13 +39,11 @@ jobs:
- name: Create Release
uses: ncipollo/release-action@v1
with:
artifacts: "dist/*"
token: ${{ secrets.GITHUB_TOKEN }}
bodyFile: "CHANGELOG.md"
draft: false
prerelease: false

- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
attestations: true

9 changes: 3 additions & 6 deletions .github/workflows/test.yml → .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,9 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Install uv
id: setup-uv
uses: astral-sh/setup-uv@v3

- name: Install the project with Python ${{ matrix.python-version }}
run: uv sync --all-extras --python ${{ matrix.python-version }}
- uses: astral-sh/setup-uv@v5
with:
python-version: ${{ matrix.python-version }}

- name: Run tests and generate coverage
run: |
Expand Down
31 changes: 6 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
[![PyPI - Version](https://img.shields.io/pypi/v/nzb?link=https%3A%2F%2Fpypi.org%2Fproject%2Fnzb%2F)](https://pypi.org/project/nzb/)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/nzb)
![License](https://img.shields.io/github/license/Ravencentric/nzb)
![Checked with mypy](https://www.mypy-lang.org/static/mypy_badge.svg)
![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)
![PyPI - Types](https://img.shields.io/pypi/types/nzb)

![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/Ravencentric/nzb/release.yml)
![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/ravencentric/nzb/test.yml?label=tests)
[![codecov](https://codecov.io/gh/Ravencentric/nzb/graph/badge.svg?token=FFSOFFOM6J)](https://codecov.io/gh/Ravencentric/nzb)

![GitHub Build Workflow Status](https://img.shields.io/github/actions/workflow/status/Ravencentric/nzb/release.yml)
![GitHub Tests Workflow Status](https://img.shields.io/github/actions/workflow/status/ravencentric/nzb/test.yml?label=tests)
[![Codecov Status](https://codecov.io/gh/Ravencentric/nzb/graph/badge.svg?token=FFSOFFOM6J)](https://codecov.io/gh/Ravencentric/nzb)

</div>

Expand All @@ -42,28 +42,9 @@ A [spec](https://sabnzbd.org/wiki/extra/nzb-spec) compliant parser and meta edit
pip install nzb
```

## Usage

```py
from nzb import NZBParser

nzb = NZBParser.from_file("Big Buck Bunny - S01E01.mkv.nzb").parse()

print(f"{nzb.file.name} ({nzb.file.size.human_readable()})")
#> Big Buck Bunny - S01E01.mkv (16.7MiB)

for file in nzb.files:
print((file.name, file.size, file.datetime.isoformat(), file.groups))
#> ("Big Buck Bunny - S01E01.mkv", 17521761, "2024-01-28T11:18:28+00:00", ("alt.binaries.boneless",))
#> ("Big Buck Bunny - S01E01.mkv.par2", 1089, "2024-01-28T11:18:29+00:00", ("alt.binaries.boneless",))
#> ("Big Buck Bunny - S01E01.mkv.vol00+01.par2", 741017, "2024-01-28T11:18:29+00:00", ("alt.binaries.boneless",))
#> ("Big Buck Bunny - S01E01.mkv.vol01+02.par2", 1480494, "2024-01-28T11:18:29+00:00", ("alt.binaries.boneless",))
#> ("Big Buck Bunny - S01E01.mkv.vol03+04.par2", 2960528, "2024-01-28T11:18:29+00:00", ("alt.binaries.boneless",))
```

## Docs

Checkout the complete documentation [here](https://nzb.ravencentric.cc/).
Checkout the [tutorial](https://nzb.ravencentric.cc/tutorial/) and the [API reference](https://nzb.ravencentric.cc/api-reference/parser/).

## License

Expand Down
5 changes: 1 addition & 4 deletions docs/api-reference/exceptions.md
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
::: nzb.NZBException
::: nzb.InvalidNZBError
options:
members: true
::: nzb.InvalidNzbError
2 changes: 1 addition & 1 deletion docs/api-reference/meta-editor.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
::: nzb.NZBMetaEditor
::: nzb.NzbMetaEditor
4 changes: 0 additions & 4 deletions docs/api-reference/models.md

This file was deleted.

5 changes: 4 additions & 1 deletion docs/api-reference/parser.md
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
::: nzb.NZBParser
::: nzb.Nzb
::: nzb.Meta
::: nzb.File
::: nzb.Segment
28 changes: 4 additions & 24 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@
<a href="https://pypi.org/project/nzb/"><img src="https://img.shields.io/pypi/v/nzb" alt="PyPI - Version" ></a>
<img src="https://img.shields.io/pypi/pyversions/nzb" alt="PyPI - Python Version">
<img src="https://img.shields.io/github/license/Ravencentric/nzb" alt="License">
<img src="https://www.mypy-lang.org/static/mypy_badge.svg" alt="Checked with mypy">
<img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff">
<img src="https://img.shields.io/pypi/types/nzb" alt="PyPI - Types">
</p>

<p align="center">
<img src="https://img.shields.io/github/actions/workflow/status/Ravencentric/nzb/release.yml?" alt="GitHub Workflow Status">
<img src="https://img.shields.io/github/actions/workflow/status/Ravencentric/nzb/test.yml?label=tests" alt="GitHub Workflow Status">
<a href="https://codecov.io/gh/Ravencentric/nzb"><img src="https://codecov.io/gh/Ravencentric/nzb/graph/badge.svg?token=FFSOFFOM6J" alt="Codecov"></a>
<img src="https://img.shields.io/github/actions/workflow/status/Ravencentric/nzb/release.yml?" alt="GitHub Build Workflow Status">
<img src="https://img.shields.io/github/actions/workflow/status/Ravencentric/nzb/test.yml?label=tests" alt="GitHub Tests Workflow Status">
<a href="https://codecov.io/gh/Ravencentric/nzb"><img src="https://codecov.io/gh/Ravencentric/nzb/graph/badge.svg?token=FFSOFFOM6J" alt="Codecov Status"></a>
</p>


Expand All @@ -37,25 +36,6 @@ A [spec](https://sabnzbd.org/wiki/extra/nzb-spec) compliant parser and meta edit
pip install nzb
```

## Usage

```py
from nzb import NZBParser

nzb = NZBParser.from_file("Big Buck Bunny - S01E01.mkv.nzb").parse()

print(f"{nzb.file.name} ({nzb.file.size.human_readable()})")
#> Big Buck Bunny - S01E01.mkv (16.7MiB)

for file in nzb.files:
print((file.name, file.size, file.datetime.isoformat(), file.groups))
#> ("Big Buck Bunny - S01E01.mkv", 17521761, "2024-01-28T11:18:28+00:00", ("alt.binaries.boneless",))
#> ("Big Buck Bunny - S01E01.mkv.par2", 1089, "2024-01-28T11:18:29+00:00", ("alt.binaries.boneless",))
#> ("Big Buck Bunny - S01E01.mkv.vol00+01.par2", 741017, "2024-01-28T11:18:29+00:00", ("alt.binaries.boneless",))
#> ("Big Buck Bunny - S01E01.mkv.vol01+02.par2", 1480494, "2024-01-28T11:18:29+00:00", ("alt.binaries.boneless",))
#> ("Big Buck Bunny - S01E01.mkv.vol03+04.par2", 2960528, "2024-01-28T11:18:29+00:00", ("alt.binaries.boneless",))
```

## License

Distributed under the [MIT](https://choosealicense.com/licenses/mit/) License. See [LICENSE](https://github.com/Ravencentric/nzb/blob/main/LICENSE) for more information.
73 changes: 73 additions & 0 deletions docs/nzb-structure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Structure of an NZB file

## Overview

[NZB is an XML-based file format for retrieving posts from NNTP (Usenet) servers](https://en.wikipedia.org/wiki/NZB).
Here's an example file:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE nzb PUBLIC "-//newzBin//DTD NZB 1.1//EN" "http://www.newzbin.com/DTD/nzb/nzb-1.1.dtd">
<nzb xmlns="http://www.newzbin.com/DTD/2003/nzb">
<head>
<meta type="title">Big Buck Bunny - S01E01.mkv</meta>
<meta type="password">secret</meta>
<meta type="tag">HD</meta>
<meta type="category">TV</meta>
</head>
<file poster="John &lt;[email protected]&gt;" date="1706440708" subject="[1/1] - &quot;Big Buck Bunny - S01E01.mkv&quot; yEnc (1/2) 1478616">
<groups>
<group>alt.binaries.boneless</group>
</groups>
<segments>
<segment bytes="739067" number="1">9cacde4c986547369becbf97003fb2c5-9483514693959@example</segment>
<segment bytes="739549" number="2">70a3a038ce324e618e2751e063d6a036-7285710986748@example</segment>
</segments>
</file>
</nzb>
```

Behind all the ugly XML, the core is pretty simple. An NZB file has optional creator-defined metadata (some of which are ["standardized"](https://sabnzbd.org/wiki/extra/nzb-spec)) and several files.

Each file has some metadata attached to it, belongs to one or more Usenet groups, and contains one or more segments.
Each segment has a unique message ID and its size in bytes.
Together, the segments form a single file.

For instance, in the example above, `file` points to a file called `Big Buck Bunny - S01E01.mkv` that belongs to the `alt.binaries.boneless` group and was broken into 2 segments, each about 739 kilobytes in size.

## Diagram

Here's a class diagram representing the structure of an NZB, which mirrors the Python implementation.

```mermaid
classDiagram
class Meta {
title: str | None
passwords: tuple[str, ...]
tags: tuple[str, ...]
category: str | None
}
class Segment {
size: int
number: int
message_id: str
}
class File {
poster: str
posted_at: datetime
subject: str
groups: tuple[str, ...]
segments: tuple[Segment, ...]
}
class Nzb {
meta: Meta
files: tuple[File, ...]
}
Nzb -- Meta
Nzb -- File
File -- Segment
```
Loading

0 comments on commit fcde6f5

Please sign in to comment.