paperless-export 0.0.2__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.
Files changed (30) hide show
  1. paperless_export-0.0.2/.env.example +9 -0
  2. paperless_export-0.0.2/.github/CODEOWNERS +1 -0
  3. paperless_export-0.0.2/.github/workflows/ci.yml +24 -0
  4. paperless_export-0.0.2/.github/workflows/release.yml +48 -0
  5. paperless_export-0.0.2/.gitignore +10 -0
  6. paperless_export-0.0.2/CHANGELOG.md +66 -0
  7. paperless_export-0.0.2/LICENSE +21 -0
  8. paperless_export-0.0.2/PKG-INFO +135 -0
  9. paperless_export-0.0.2/README.md +110 -0
  10. paperless_export-0.0.2/pyproject.toml +86 -0
  11. paperless_export-0.0.2/renovate.json +37 -0
  12. paperless_export-0.0.2/src/paperless_export/__init__.py +3 -0
  13. paperless_export-0.0.2/src/paperless_export/__main__.py +5 -0
  14. paperless_export-0.0.2/src/paperless_export/cli.py +219 -0
  15. paperless_export-0.0.2/src/paperless_export/embed.py +50 -0
  16. paperless_export-0.0.2/src/paperless_export/errors.py +46 -0
  17. paperless_export-0.0.2/src/paperless_export/exporter.py +120 -0
  18. paperless_export-0.0.2/src/paperless_export/manifest.py +90 -0
  19. paperless_export-0.0.2/src/paperless_export/preflight.py +39 -0
  20. paperless_export-0.0.2/src/paperless_export/py.typed +0 -0
  21. paperless_export-0.0.2/src/paperless_export/taxview.py +106 -0
  22. paperless_export-0.0.2/tests/__init__.py +0 -0
  23. paperless_export-0.0.2/tests/conftest.py +98 -0
  24. paperless_export-0.0.2/tests/test_cli.py +86 -0
  25. paperless_export-0.0.2/tests/test_embed.py +52 -0
  26. paperless_export-0.0.2/tests/test_exporter.py +87 -0
  27. paperless_export-0.0.2/tests/test_manifest.py +64 -0
  28. paperless_export-0.0.2/tests/test_preflight.py +37 -0
  29. paperless_export-0.0.2/tests/test_taxview.py +87 -0
  30. paperless_export-0.0.2/uv.lock +759 -0
@@ -0,0 +1,9 @@
1
+ # Copy to .env (never commit the real one) or export in your shell.
2
+ # Both are optional: they enable the API preflight check (fail fast on a bad
3
+ # token before running the exporter). Token: Paperless → Settings → API Tokens.
4
+ PAPERLESS_URL=https://paperless.local:8000
5
+ PAPERLESS_TOKEN=your-token-here
6
+
7
+ # Override how document_exporter is invoked if Paperless doesn't run via
8
+ # `docker compose exec -T webserver ...` (e.g. bare-metal or a named container).
9
+ #PAPERLESS_EXPORTER_CMD=docker exec -i paperless-webserver document_exporter
@@ -0,0 +1 @@
1
+ * @gykonik
@@ -0,0 +1,24 @@
1
+ name: ci
2
+ on: [push, pull_request, workflow_dispatch]
3
+
4
+ jobs:
5
+ quality:
6
+ runs-on: ubuntu-latest
7
+ steps:
8
+ - uses: actions/checkout@v4
9
+ - uses: astral-sh/setup-uv@v5
10
+ - run: uv sync --all-extras --dev
11
+
12
+ - name: lint
13
+ run: |
14
+ uv run ruff check .
15
+ uv run ruff format --check .
16
+
17
+ - name: typecheck
18
+ run: uv run mypy
19
+
20
+ - name: test
21
+ run: uv run pytest -q
22
+
23
+ - name: build
24
+ run: uv build
@@ -0,0 +1,48 @@
1
+ name: release
2
+ on:
3
+ push:
4
+ branches: [main]
5
+
6
+ permissions:
7
+ contents: write # tag + GitHub Release
8
+ id-token: write # PyPI Trusted Publishing (OIDC, no token)
9
+
10
+ jobs:
11
+ release:
12
+ runs-on: ubuntu-latest
13
+ concurrency: release
14
+ steps:
15
+ # `git push` authenticates with the credentials checkout persists into the
16
+ # remote's extraheader — NOT with the token handed to the semantic-release
17
+ # action below (that one only signs GitHub API calls). The version commit
18
+ # lands on protected `main`, so the pushing identity needs a ruleset bypass:
19
+ # SEMANTIC_RELEASE_TOKEN is a PAT acting as an org owner, who has one.
20
+ - uses: actions/checkout@v4
21
+ with:
22
+ fetch-depth: 0
23
+ persist-credentials: true
24
+ token: ${{ secrets.SEMANTIC_RELEASE_TOKEN || secrets.GITHUB_TOKEN }}
25
+
26
+ - name: Semantic release (version, tag, changelog, GitHub Release)
27
+ id: semrel
28
+ uses: python-semantic-release/python-semantic-release@v9
29
+ with:
30
+ github_token: ${{ secrets.SEMANTIC_RELEASE_TOKEN || secrets.GITHUB_TOKEN }}
31
+
32
+ # No build step here on purpose. python-semantic-release already builds the
33
+ # sdist + wheel into dist/ via its `build_command` in pyproject.toml. It is
34
+ # a Docker action running as root, so those files are root-owned; a second
35
+ # `uv build` as the unprivileged runner user cannot overwrite them and dies
36
+ # with PermissionError, taking publish and the brew bump down with it.
37
+ - name: Publish to PyPI (OIDC)
38
+ if: steps.semrel.outputs.released == 'true'
39
+ uses: pypa/gh-action-pypi-publish@release/v1
40
+
41
+ - name: Bump Homebrew formula
42
+ if: steps.semrel.outputs.released == 'true'
43
+ run: |
44
+ gh workflow run bump.yml -R fileworks/homebrew-tap \
45
+ -f formula=paperless-export \
46
+ -f version=${{ steps.semrel.outputs.version }}
47
+ env:
48
+ GH_TOKEN: ${{ secrets.TAP_DISPATCH_TOKEN }}
@@ -0,0 +1,10 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .venv/
4
+ .pytest_cache/
5
+ .mypy_cache/
6
+ .ruff_cache/
7
+ dist/
8
+ *.egg-info/
9
+ .env
10
+ .DS_Store
@@ -0,0 +1,66 @@
1
+ # CHANGELOG
2
+
3
+
4
+ ## v0.0.2 (2026-07-13)
5
+
6
+ ### Bug Fixes
7
+
8
+ - **release**: Drop the duplicate build that broke publishing
9
+ ([#3](https://github.com/fileworks/paperless-export/pull/3),
10
+ [`a51f396`](https://github.com/fileworks/paperless-export/commit/a51f3963604e0777966a317f01d27cc9f1eec1bc))
11
+
12
+ The release job died at 'Build sdist + wheel' with
13
+
14
+ PermissionError: [Errno 13] Permission denied: dist/<pkg>-0.0.1.tar.gz
15
+
16
+ python-semantic-release already builds the sdist and wheel into dist/ via the build_command in
17
+ pyproject.toml. It is a Docker action running as root, so those artefacts are root-owned. The
18
+ workflow then ran a second, redundant 'uv build' as the unprivileged runner user, which cannot
19
+ overwrite them.
20
+
21
+ Publish to PyPI and the Homebrew bump are both gated on that step, so a permission error on a build
22
+ that never needed to happen silently took out the entire release.
23
+
24
+ Remove the duplicate build and the setup-uv step that only served it, and let the publish action
25
+ consume the dist/ that semantic-release produced.
26
+
27
+
28
+ ## v0.0.1 (2026-07-12)
29
+
30
+ ### Bug Fixes
31
+
32
+ - **release**: Give checkout the release token so the version push is allowed
33
+ ([#2](https://github.com/fileworks/paperless-export/pull/2),
34
+ [`e201478`](https://github.com/fileworks/paperless-export/commit/e201478af0f822dbe19163edcfb1431f4427926d))
35
+
36
+ The release job fails with GH013 — the chore(release) version commit cannot be pushed to protected
37
+ main.
38
+
39
+ Handing SEMANTIC_RELEASE_TOKEN to the python-semantic-release action is not enough: that input only
40
+ authenticates GitHub API calls. The actual git push uses the credentials actions/checkout persists
41
+ into the remote's extraheader, which were still the default GITHUB_TOKEN — an identity with no
42
+ ruleset bypass.
43
+
44
+ Set the token on checkout as well, mirroring media-sorter's semantic-release workflow, so the push
45
+ authenticates as an org owner and the always-bypass applies.
46
+
47
+ ### Continuous Integration
48
+
49
+ - Allow CI to be triggered manually ([#1](https://github.com/fileworks/paperless-export/pull/1),
50
+ [`ff5c192`](https://github.com/fileworks/paperless-export/commit/ff5c192cfcca77171f324f6f200c136a0a9f9879))
51
+
52
+ * ci: allow CI to be triggered manually
53
+
54
+ workflow_dispatch makes it possible to re-run checks without pushing a commit — needed while
55
+ verifying the org's Actions allow-list, and useful any time a run fails for reasons outside the
56
+ code.
57
+
58
+ * fix(release): push the version commit with a token that can bypass the ruleset
59
+
60
+ semantic-release commits the version bump to main. The branch ruleset requires a PR, and the default
61
+ GITHUB_TOKEN has no bypass — GitHub rejects the Actions app as a bypass actor ("must be part of
62
+ the ruleset source or owner organization"), so the release job could never land its commit.
63
+
64
+ SEMANTIC_RELEASE_TOKEN is a fine-grained PAT that acts as an org owner, who already holds an
65
+ always-bypass on the ruleset. Falls back to GITHUB_TOKEN so nothing breaks where the secret is
66
+ absent.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Niklas Büchel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,135 @@
1
+ Metadata-Version: 2.4
2
+ Name: paperless-export
3
+ Version: 0.0.2
4
+ Summary: Scheduled wrapper around Paperless-ngx's document_exporter plus a _Steuer/YYYY tax-view post-processor.
5
+ Project-URL: Repository, https://github.com/fileworks/paperless-export
6
+ Project-URL: Issues, https://github.com/fileworks/paperless-export/issues
7
+ Author: gykonik
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: backup,documents,export,paperless-ngx
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: End Users/Desktop
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: System :: Archiving :: Backup
18
+ Requires-Python: >=3.12
19
+ Requires-Dist: httpx>=0.28
20
+ Requires-Dist: pydantic>=2.9
21
+ Requires-Dist: typer>=0.15
22
+ Provides-Extra: pdf
23
+ Requires-Dist: pikepdf>=9.0; extra == 'pdf'
24
+ Description-Content-Type: text/markdown
25
+
26
+ # paperless-export
27
+
28
+ A thin scheduled wrapper around [Paperless-ngx](https://docs.paperless-ngx.com)'s
29
+ built-in `document_exporter`, plus the one thing it doesn't do: a materialized
30
+ **`_Steuer/YYYY/` tax view** built from your `Steuer-YYYY` tags.
31
+
32
+ Paperless's exporter already produces the full no-lock-in export — every
33
+ document laid out by your storage-path template, originals *and* PDF/A archive
34
+ versions, and a complete `manifest.json` (tags, correspondents, types, custom
35
+ fields). This tool deliberately does **not** rebuild any of that. It:
36
+
37
+ 1. runs `document_exporter <target> --use-filename-format --compare-checksums --delete`
38
+ (each flag toggleable), surfacing failures honestly and **falling back to a
39
+ flat export with a clear warning when a path exceeds the OS limit**,
40
+ 2. reads `manifest.json` and builds `_Steuer/<YYYY>/` — one symlink (or copy)
41
+ per document tagged `Steuer-YYYY` — plus a greppable `_Steuer/INDEX.csv`,
42
+ 3. optionally embeds tags/correspondent/type into the exported PDFs' XMP
43
+ (`--embed-tags`, needs the `[pdf]` extra).
44
+
45
+ ```
46
+ export/
47
+ Bescheid/Finanzamt/2024-05-01 Steuerbescheid.pdf # ← document_exporter
48
+ manifest.json # ← document_exporter
49
+ _Steuer/
50
+ 2024/2024-05-01 Steuerbescheid.pdf → ../../Bescheid/Finanzamt/…
51
+ INDEX.csv # year,title,correspondent,created,original_path
52
+ ```
53
+
54
+ ## Install
55
+
56
+ ```sh
57
+ pipx install paperless-export # + 'paperless-export[pdf]' for --embed-tags
58
+ # or
59
+ brew install fileworks/tap/paperless-export
60
+ ```
61
+
62
+ *(Not yet published — first release pending; until then: `uv run paperless-export` from a checkout.)*
63
+
64
+ ## Usage
65
+
66
+ ```sh
67
+ # the nightly job (run from the directory containing your compose file):
68
+ paperless-export run --export-dir /volume1/paperless/export
69
+
70
+ # rebuild only the tax view from an existing export:
71
+ paperless-export tax-view --export-dir /volume1/paperless/export
72
+
73
+ # FAT/exFAT or cloud targets that don't preserve symlinks:
74
+ paperless-export run --export-dir ./export --copy
75
+ ```
76
+
77
+ Notes:
78
+
79
+ - `--exporter-target` (default `../export`) is the path **as the exporter
80
+ process sees it** inside the container; `--export-dir` is the same directory
81
+ **on this host**. With the standard compose setup they're the same bind mount.
82
+ - `PAPERLESS_URL` + `PAPERLESS_TOKEN` (env or flags) enable a preflight check
83
+ so a bad token fails fast with a clear message — they're optional because the
84
+ exporter itself runs inside the container and needs no API access.
85
+ - `--embed-tags` rewrites the exported PDFs, which changes their checksums, so
86
+ those files are re-exported on the next `--compare-checksums` run. The
87
+ manifest already preserves all metadata — only embed if you want tags
88
+ *inside* the files.
89
+
90
+ ## Behavior guarantees
91
+
92
+ - **Read-only against Paperless** — writes only into the export directory.
93
+ - **Idempotent** — the `_Steuer/` view is rebuilt from scratch each run; safe nightly.
94
+ - **Verifiable** — after a run, `_Steuer/2025/` contains exactly the documents
95
+ tagged `Steuer-2025`; `INDEX.csv` matches a manifest query.
96
+ - **Honest failures** — a non-zero `document_exporter` exit surfaces its stderr
97
+ and exit code; symlink-unsupported filesystems auto-switch to copies with a notice.
98
+
99
+ ## Exit codes
100
+
101
+ | Code | Meaning |
102
+ |---|---|
103
+ | 0 | success |
104
+ | 2 | bad configuration / authentication failure |
105
+ | 3 | Paperless (or Docker) not reachable |
106
+ | 4 | export dir missing / manifest unreadable |
107
+ | *n* | `document_exporter` failed with exit code *n* |
108
+
109
+ ## Scheduling on a Synology (DSM Task Scheduler)
110
+
111
+ ```sh
112
+ cd /volume1/docker/paperless && \
113
+ /usr/local/bin/paperless-export run --export-dir /volume1/paperless/export
114
+ ```
115
+
116
+ Nightly, after the Paperless backup window; the export target should live on a
117
+ share covered by your backup chain.
118
+
119
+ ## Development
120
+
121
+ ```sh
122
+ uv sync --all-extras --dev
123
+ uv run ruff check . && uv run ruff format --check . # lint
124
+ uv run mypy # strict types
125
+ uv run pytest # tests
126
+ uv build
127
+ ```
128
+
129
+ Conventional Commits drive releases (`python-semantic-release`): merge to
130
+ `main` → version bump + changelog + GitHub Release + PyPI publish (OIDC) +
131
+ Homebrew formula bump.
132
+
133
+ ## License
134
+
135
+ MIT
@@ -0,0 +1,110 @@
1
+ # paperless-export
2
+
3
+ A thin scheduled wrapper around [Paperless-ngx](https://docs.paperless-ngx.com)'s
4
+ built-in `document_exporter`, plus the one thing it doesn't do: a materialized
5
+ **`_Steuer/YYYY/` tax view** built from your `Steuer-YYYY` tags.
6
+
7
+ Paperless's exporter already produces the full no-lock-in export — every
8
+ document laid out by your storage-path template, originals *and* PDF/A archive
9
+ versions, and a complete `manifest.json` (tags, correspondents, types, custom
10
+ fields). This tool deliberately does **not** rebuild any of that. It:
11
+
12
+ 1. runs `document_exporter <target> --use-filename-format --compare-checksums --delete`
13
+ (each flag toggleable), surfacing failures honestly and **falling back to a
14
+ flat export with a clear warning when a path exceeds the OS limit**,
15
+ 2. reads `manifest.json` and builds `_Steuer/<YYYY>/` — one symlink (or copy)
16
+ per document tagged `Steuer-YYYY` — plus a greppable `_Steuer/INDEX.csv`,
17
+ 3. optionally embeds tags/correspondent/type into the exported PDFs' XMP
18
+ (`--embed-tags`, needs the `[pdf]` extra).
19
+
20
+ ```
21
+ export/
22
+ Bescheid/Finanzamt/2024-05-01 Steuerbescheid.pdf # ← document_exporter
23
+ manifest.json # ← document_exporter
24
+ _Steuer/
25
+ 2024/2024-05-01 Steuerbescheid.pdf → ../../Bescheid/Finanzamt/…
26
+ INDEX.csv # year,title,correspondent,created,original_path
27
+ ```
28
+
29
+ ## Install
30
+
31
+ ```sh
32
+ pipx install paperless-export # + 'paperless-export[pdf]' for --embed-tags
33
+ # or
34
+ brew install fileworks/tap/paperless-export
35
+ ```
36
+
37
+ *(Not yet published — first release pending; until then: `uv run paperless-export` from a checkout.)*
38
+
39
+ ## Usage
40
+
41
+ ```sh
42
+ # the nightly job (run from the directory containing your compose file):
43
+ paperless-export run --export-dir /volume1/paperless/export
44
+
45
+ # rebuild only the tax view from an existing export:
46
+ paperless-export tax-view --export-dir /volume1/paperless/export
47
+
48
+ # FAT/exFAT or cloud targets that don't preserve symlinks:
49
+ paperless-export run --export-dir ./export --copy
50
+ ```
51
+
52
+ Notes:
53
+
54
+ - `--exporter-target` (default `../export`) is the path **as the exporter
55
+ process sees it** inside the container; `--export-dir` is the same directory
56
+ **on this host**. With the standard compose setup they're the same bind mount.
57
+ - `PAPERLESS_URL` + `PAPERLESS_TOKEN` (env or flags) enable a preflight check
58
+ so a bad token fails fast with a clear message — they're optional because the
59
+ exporter itself runs inside the container and needs no API access.
60
+ - `--embed-tags` rewrites the exported PDFs, which changes their checksums, so
61
+ those files are re-exported on the next `--compare-checksums` run. The
62
+ manifest already preserves all metadata — only embed if you want tags
63
+ *inside* the files.
64
+
65
+ ## Behavior guarantees
66
+
67
+ - **Read-only against Paperless** — writes only into the export directory.
68
+ - **Idempotent** — the `_Steuer/` view is rebuilt from scratch each run; safe nightly.
69
+ - **Verifiable** — after a run, `_Steuer/2025/` contains exactly the documents
70
+ tagged `Steuer-2025`; `INDEX.csv` matches a manifest query.
71
+ - **Honest failures** — a non-zero `document_exporter` exit surfaces its stderr
72
+ and exit code; symlink-unsupported filesystems auto-switch to copies with a notice.
73
+
74
+ ## Exit codes
75
+
76
+ | Code | Meaning |
77
+ |---|---|
78
+ | 0 | success |
79
+ | 2 | bad configuration / authentication failure |
80
+ | 3 | Paperless (or Docker) not reachable |
81
+ | 4 | export dir missing / manifest unreadable |
82
+ | *n* | `document_exporter` failed with exit code *n* |
83
+
84
+ ## Scheduling on a Synology (DSM Task Scheduler)
85
+
86
+ ```sh
87
+ cd /volume1/docker/paperless && \
88
+ /usr/local/bin/paperless-export run --export-dir /volume1/paperless/export
89
+ ```
90
+
91
+ Nightly, after the Paperless backup window; the export target should live on a
92
+ share covered by your backup chain.
93
+
94
+ ## Development
95
+
96
+ ```sh
97
+ uv sync --all-extras --dev
98
+ uv run ruff check . && uv run ruff format --check . # lint
99
+ uv run mypy # strict types
100
+ uv run pytest # tests
101
+ uv build
102
+ ```
103
+
104
+ Conventional Commits drive releases (`python-semantic-release`): merge to
105
+ `main` → version bump + changelog + GitHub Release + PyPI publish (OIDC) +
106
+ Homebrew formula bump.
107
+
108
+ ## License
109
+
110
+ MIT
@@ -0,0 +1,86 @@
1
+ [project]
2
+ name = "paperless-export"
3
+ version = "0.0.2"
4
+ description = "Scheduled wrapper around Paperless-ngx's document_exporter plus a _Steuer/YYYY tax-view post-processor."
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ license-files = ["LICENSE"]
8
+ authors = [{ name = "gykonik" }]
9
+ requires-python = ">=3.12"
10
+ keywords = ["paperless-ngx", "export", "backup", "documents"]
11
+ classifiers = [
12
+ "Development Status :: 4 - Beta",
13
+ "Environment :: Console",
14
+ "Intended Audience :: End Users/Desktop",
15
+ "Operating System :: OS Independent",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Programming Language :: Python :: 3.13",
18
+ "Topic :: System :: Archiving :: Backup",
19
+ ]
20
+ dependencies = [
21
+ "httpx>=0.28",
22
+ "pydantic>=2.9",
23
+ "typer>=0.15",
24
+ ]
25
+
26
+ [project.optional-dependencies]
27
+ pdf = ["pikepdf>=9.0"]
28
+
29
+ [project.urls]
30
+ Repository = "https://github.com/fileworks/paperless-export"
31
+ Issues = "https://github.com/fileworks/paperless-export/issues"
32
+
33
+ [project.scripts]
34
+ paperless-export = "paperless_export.cli:app"
35
+
36
+ [dependency-groups]
37
+ dev = [
38
+ "mypy>=1.13",
39
+ "pikepdf>=9.0",
40
+ "pytest>=8.3",
41
+ "respx>=0.22",
42
+ "ruff>=0.8",
43
+ ]
44
+
45
+ [build-system]
46
+ requires = ["hatchling"]
47
+ build-backend = "hatchling.build"
48
+
49
+ [tool.hatch.build.targets.wheel]
50
+ packages = ["src/paperless_export"]
51
+
52
+ [tool.ruff]
53
+ line-length = 100
54
+ target-version = "py312"
55
+
56
+ [tool.ruff.lint]
57
+ select = ["E", "F", "I", "N", "UP", "B", "A", "C4", "SIM", "RUF", "PTH", "RET", "ARG"]
58
+
59
+ [tool.ruff.lint.per-file-ignores]
60
+ # pytest fixtures are frequently used only for their side effect
61
+ "tests/**" = ["ARG001"]
62
+
63
+ [tool.mypy]
64
+ python_version = "3.12"
65
+ strict = true
66
+ files = ["src", "tests"]
67
+
68
+ [[tool.mypy.overrides]]
69
+ module = "pikepdf.*"
70
+ ignore_missing_imports = true
71
+
72
+ [tool.pytest.ini_options]
73
+ testpaths = ["tests"]
74
+
75
+ [tool.semantic_release]
76
+ version_toml = ["pyproject.toml:project.version"]
77
+ version_variables = ["src/paperless_export/__init__.py:__version__"]
78
+ commit_message = "chore(release): {version} [skip ci]"
79
+ build_command = "python -m pip install uv && uv build"
80
+ allow_zero_version = true
81
+
82
+ [tool.semantic_release.branches.main]
83
+ match = "main"
84
+
85
+ [tool.semantic_release.changelog.default_templates]
86
+ changelog_file = "CHANGELOG.md"
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3
+ "extends": ["config:recommended", ":semanticCommits", ":dependencyDashboard"],
4
+ "timezone": "Europe/Berlin",
5
+ "schedule": ["before 6am on monday"],
6
+ "prConcurrentLimit": 5,
7
+ "lockFileMaintenance": {
8
+ "enabled": true,
9
+ "schedule": ["before 6am on the first day of the month"]
10
+ },
11
+ "vulnerabilityAlerts": {
12
+ "labels": ["security"],
13
+ "schedule": ["at any time"],
14
+ "automerge": true
15
+ },
16
+ "packageRules": [
17
+ {
18
+ "description": "Auto-merge patch/minor once CI (lint/typecheck/test/build) is green — low risk, keeps the tree current without manual review.",
19
+ "matchUpdateTypes": ["patch", "minor", "digest"],
20
+ "automerge": true,
21
+ "automergeType": "pr",
22
+ "platformAutomerge": true
23
+ },
24
+ {
25
+ "description": "Major bumps always get a PR, never auto-merged — API/behaviour changes need a look.",
26
+ "matchUpdateTypes": ["major"],
27
+ "automerge": false,
28
+ "labels": ["major-update"]
29
+ },
30
+ {
31
+ "description": "Group all GitHub Actions bumps into one PR.",
32
+ "matchManagers": ["github-actions"],
33
+ "groupName": "GitHub Actions",
34
+ "automerge": true
35
+ }
36
+ ]
37
+ }
@@ -0,0 +1,3 @@
1
+ """paperless-export — Paperless-ngx export wrapper + _Steuer/YYYY tax view."""
2
+
3
+ __version__ = "0.0.2"
@@ -0,0 +1,5 @@
1
+ """Allow `python -m paperless_export`."""
2
+
3
+ from .cli import app
4
+
5
+ app()