yinv 0.1.0__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.
- yinv-0.1.0/.gitignore +28 -0
- yinv-0.1.0/CHANGELOG.md +17 -0
- yinv-0.1.0/LICENSE +21 -0
- yinv-0.1.0/PKG-INFO +145 -0
- yinv-0.1.0/README.md +98 -0
- yinv-0.1.0/RELEASING.md +95 -0
- yinv-0.1.0/pyproject.toml +57 -0
- yinv-0.1.0/src/yinv/__init__.py +10 -0
- yinv-0.1.0/src/yinv/__main__.py +6 -0
- yinv-0.1.0/src/yinv/cli.py +302 -0
- yinv-0.1.0/src/yinv/config.py +177 -0
- yinv-0.1.0/src/yinv/data.py +338 -0
- yinv-0.1.0/src/yinv/dates.py +78 -0
- yinv-0.1.0/src/yinv/render.py +124 -0
- yinv-0.1.0/src/yinv/templates/invoice.css +179 -0
- yinv-0.1.0/src/yinv/templates/invoice.html.jinja +119 -0
- yinv-0.1.0/src/yinv/templates/seed.yaml +46 -0
- yinv-0.1.0/tests/fixtures/example.yaml +51 -0
- yinv-0.1.0/tests/test_config.py +81 -0
- yinv-0.1.0/tests/test_data.py +414 -0
- yinv-0.1.0/tests/test_dates.py +98 -0
yinv-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Python build artifacts
|
|
2
|
+
dist/
|
|
3
|
+
build/
|
|
4
|
+
*.egg-info/
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.pyc
|
|
7
|
+
*.pyo
|
|
8
|
+
.pytest_cache/
|
|
9
|
+
.ruff_cache/
|
|
10
|
+
|
|
11
|
+
# Virtual environments
|
|
12
|
+
.venv/
|
|
13
|
+
venv/
|
|
14
|
+
env/
|
|
15
|
+
|
|
16
|
+
# IDE
|
|
17
|
+
.vscode/
|
|
18
|
+
.idea/
|
|
19
|
+
*.swp
|
|
20
|
+
|
|
21
|
+
# OS
|
|
22
|
+
.DS_Store
|
|
23
|
+
|
|
24
|
+
# Privacy: never commit real invoice data or generated PDFs
|
|
25
|
+
# from any stray local runs at the repo root.
|
|
26
|
+
/*.pdf
|
|
27
|
+
/*.yaml
|
|
28
|
+
/invoices/
|
yinv-0.1.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to yinv will be documented here.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2026-04-12
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Initial implementation: `yinv new`, `yinv render`, `yinv config set/get`.
|
|
14
|
+
- YAML schema with explicit `service_month`, `client`, line-item descriptions.
|
|
15
|
+
- Bundled `seed.yaml` placeholder for first-run bootstrap.
|
|
16
|
+
- HTML/CSS → PDF rendering via WeasyPrint.
|
|
17
|
+
- Multi-client-ready data layout and config shape (single-client CLI in v0.1).
|
yinv-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nicolas Maldonado
|
|
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.
|
yinv-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: yinv
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CLI to generate monthly consulting invoices as PDFs from YAML
|
|
5
|
+
Author: Nicolas Maldonado
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Nicolas Maldonado
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Keywords: billing,cli,invoice,pdf,yaml
|
|
29
|
+
Classifier: Development Status :: 3 - Alpha
|
|
30
|
+
Classifier: Environment :: Console
|
|
31
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
32
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
33
|
+
Classifier: Operating System :: MacOS
|
|
34
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
35
|
+
Classifier: Programming Language :: Python :: 3
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
38
|
+
Classifier: Topic :: Office/Business
|
|
39
|
+
Requires-Python: >=3.11
|
|
40
|
+
Requires-Dist: jinja2>=3.1
|
|
41
|
+
Requires-Dist: pyyaml>=6.0
|
|
42
|
+
Requires-Dist: weasyprint>=60.0
|
|
43
|
+
Provides-Extra: dev
|
|
44
|
+
Requires-Dist: build>=1.0; extra == 'dev'
|
|
45
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
46
|
+
Description-Content-Type: text/markdown
|
|
47
|
+
|
|
48
|
+
# yinv
|
|
49
|
+
|
|
50
|
+
CLI to generate monthly consulting invoices as PDFs. You edit a YAML draft in
|
|
51
|
+
your `$EDITOR`, save, and get a PDF that matches a consistent template.
|
|
52
|
+
|
|
53
|
+
## Install (dev)
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
brew install pango gdk-pixbuf libffi
|
|
57
|
+
uv tool install . # or: pipx install .
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Configure
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
yinv config set invoices.dir ~/Documents/Invoices
|
|
64
|
+
yinv config set client.default <your-client-subdir-name>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`invoices.dir` is the parent dir containing one subdir per client. Each
|
|
68
|
+
client's invoices live under `{invoices.dir}/{client}/{year}/`.
|
|
69
|
+
|
|
70
|
+
## Use
|
|
71
|
+
|
|
72
|
+
### First run
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
yinv new
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
If no prior invoice exists for `client.default`, `yinv new` writes a
|
|
79
|
+
placeholder YAML into the correct path and opens it in `$EDITOR`.
|
|
80
|
+
|
|
81
|
+
Fill in the placeholders (name, address, bank details, line items), then save
|
|
82
|
+
and exit your editor. `yinv new` will validate the YAML and generate the PDF
|
|
83
|
+
automatically after the editor exits successfully.
|
|
84
|
+
|
|
85
|
+
The seed file still contains placeholder contact, bank, and pricing values,
|
|
86
|
+
but the default `Consulting fees for <Month YYYY>` description is adjusted to
|
|
87
|
+
the target service month automatically.
|
|
88
|
+
|
|
89
|
+
### Monthly
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
yinv new
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Forks the latest invoice, increments the number, rolls the month forward
|
|
96
|
+
(updating dates and exact `Month YYYY` tokens in line-item descriptions),
|
|
97
|
+
opens in `$EDITOR` for review, and renders the PDF after the editor exits
|
|
98
|
+
successfully.
|
|
99
|
+
|
|
100
|
+
Example: if the previous invoice contains `Consulting fees for April 2026`,
|
|
101
|
+
the next one will become `Consulting fees for May 2026`.
|
|
102
|
+
|
|
103
|
+
The month rewrite is intentionally narrow: it only replaces the exact previous
|
|
104
|
+
invoice service-month token. If the prior invoice still says `January 2026` or
|
|
105
|
+
uses a different format such as `Jan 2026`, that text will be carried forward
|
|
106
|
+
unchanged.
|
|
107
|
+
|
|
108
|
+
`yinv new --month 2026-07` targets a specific month (skip ahead / regenerate).
|
|
109
|
+
`yinv new --force` overwrites an existing target.
|
|
110
|
+
|
|
111
|
+
### Re-render
|
|
112
|
+
|
|
113
|
+
```sh
|
|
114
|
+
yinv render <file.yaml>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Writes a fresh PDF next to the YAML. Useful after manually editing a YAML.
|
|
118
|
+
This is mainly for re-rendering an existing invoice; `yinv new` already renders
|
|
119
|
+
the new month's PDF automatically after a successful editor exit.
|
|
120
|
+
|
|
121
|
+
## Commands (v0.1)
|
|
122
|
+
|
|
123
|
+
| Command | Purpose |
|
|
124
|
+
|---|---|
|
|
125
|
+
| `yinv new [--month YYYY-MM] [--force]` | First-run bootstrap or monthly fork. |
|
|
126
|
+
| `yinv render <file.yaml>` | Render one YAML to PDF. |
|
|
127
|
+
| `yinv config set <key> <value>` | Write a config key. |
|
|
128
|
+
| `yinv config get <key>` | Read a config key. |
|
|
129
|
+
|
|
130
|
+
## Data layout
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
~/Documents/Invoices/ ← invoices.dir
|
|
134
|
+
└── <client>/ ← one subdir per client
|
|
135
|
+
└── 2026/
|
|
136
|
+
├── March2026.yaml ← source of truth
|
|
137
|
+
└── March2026.pdf ← generated from the YAML
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Nothing else. No database, no index file. Add another client tomorrow by
|
|
141
|
+
creating another subdir.
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
MIT. See `LICENSE`.
|
yinv-0.1.0/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# yinv
|
|
2
|
+
|
|
3
|
+
CLI to generate monthly consulting invoices as PDFs. You edit a YAML draft in
|
|
4
|
+
your `$EDITOR`, save, and get a PDF that matches a consistent template.
|
|
5
|
+
|
|
6
|
+
## Install (dev)
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
brew install pango gdk-pixbuf libffi
|
|
10
|
+
uv tool install . # or: pipx install .
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Configure
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
yinv config set invoices.dir ~/Documents/Invoices
|
|
17
|
+
yinv config set client.default <your-client-subdir-name>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`invoices.dir` is the parent dir containing one subdir per client. Each
|
|
21
|
+
client's invoices live under `{invoices.dir}/{client}/{year}/`.
|
|
22
|
+
|
|
23
|
+
## Use
|
|
24
|
+
|
|
25
|
+
### First run
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
yinv new
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
If no prior invoice exists for `client.default`, `yinv new` writes a
|
|
32
|
+
placeholder YAML into the correct path and opens it in `$EDITOR`.
|
|
33
|
+
|
|
34
|
+
Fill in the placeholders (name, address, bank details, line items), then save
|
|
35
|
+
and exit your editor. `yinv new` will validate the YAML and generate the PDF
|
|
36
|
+
automatically after the editor exits successfully.
|
|
37
|
+
|
|
38
|
+
The seed file still contains placeholder contact, bank, and pricing values,
|
|
39
|
+
but the default `Consulting fees for <Month YYYY>` description is adjusted to
|
|
40
|
+
the target service month automatically.
|
|
41
|
+
|
|
42
|
+
### Monthly
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
yinv new
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Forks the latest invoice, increments the number, rolls the month forward
|
|
49
|
+
(updating dates and exact `Month YYYY` tokens in line-item descriptions),
|
|
50
|
+
opens in `$EDITOR` for review, and renders the PDF after the editor exits
|
|
51
|
+
successfully.
|
|
52
|
+
|
|
53
|
+
Example: if the previous invoice contains `Consulting fees for April 2026`,
|
|
54
|
+
the next one will become `Consulting fees for May 2026`.
|
|
55
|
+
|
|
56
|
+
The month rewrite is intentionally narrow: it only replaces the exact previous
|
|
57
|
+
invoice service-month token. If the prior invoice still says `January 2026` or
|
|
58
|
+
uses a different format such as `Jan 2026`, that text will be carried forward
|
|
59
|
+
unchanged.
|
|
60
|
+
|
|
61
|
+
`yinv new --month 2026-07` targets a specific month (skip ahead / regenerate).
|
|
62
|
+
`yinv new --force` overwrites an existing target.
|
|
63
|
+
|
|
64
|
+
### Re-render
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
yinv render <file.yaml>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Writes a fresh PDF next to the YAML. Useful after manually editing a YAML.
|
|
71
|
+
This is mainly for re-rendering an existing invoice; `yinv new` already renders
|
|
72
|
+
the new month's PDF automatically after a successful editor exit.
|
|
73
|
+
|
|
74
|
+
## Commands (v0.1)
|
|
75
|
+
|
|
76
|
+
| Command | Purpose |
|
|
77
|
+
|---|---|
|
|
78
|
+
| `yinv new [--month YYYY-MM] [--force]` | First-run bootstrap or monthly fork. |
|
|
79
|
+
| `yinv render <file.yaml>` | Render one YAML to PDF. |
|
|
80
|
+
| `yinv config set <key> <value>` | Write a config key. |
|
|
81
|
+
| `yinv config get <key>` | Read a config key. |
|
|
82
|
+
|
|
83
|
+
## Data layout
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
~/Documents/Invoices/ ← invoices.dir
|
|
87
|
+
└── <client>/ ← one subdir per client
|
|
88
|
+
└── 2026/
|
|
89
|
+
├── March2026.yaml ← source of truth
|
|
90
|
+
└── March2026.pdf ← generated from the YAML
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Nothing else. No database, no index file. Add another client tomorrow by
|
|
94
|
+
creating another subdir.
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
MIT. See `LICENSE`.
|
yinv-0.1.0/RELEASING.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Releasing yinv
|
|
2
|
+
|
|
3
|
+
## Pre-release checklist
|
|
4
|
+
|
|
5
|
+
Before pushing to a public GitHub repo or publishing to PyPI:
|
|
6
|
+
|
|
7
|
+
### Privacy audit
|
|
8
|
+
|
|
9
|
+
Maintain a **local, uncommitted** list of your real private values — client
|
|
10
|
+
name, personal name, home address tokens, client address tokens, account
|
|
11
|
+
number, routing number, SWIFT/BIC, bank name. Call it something you'll
|
|
12
|
+
recognize (e.g. `~/.yinv-privacy-audit-terms` — add it to your global
|
|
13
|
+
`~/.gitignore_global`).
|
|
14
|
+
|
|
15
|
+
Then, from the repo root:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
# Every term must return zero matches:
|
|
19
|
+
while IFS= read -r term; do
|
|
20
|
+
echo "=== $term ==="
|
|
21
|
+
git grep -i -- "$term" || true
|
|
22
|
+
done < ~/.yinv-privacy-audit-terms
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
As a positive control, confirm the synthetic fixture tokens **do** appear —
|
|
26
|
+
this proves the fixture is still synthetic and hasn't been silently replaced
|
|
27
|
+
with real data:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
git grep -i "0000000000" # should return tests/fixtures/example.yaml + seed.yaml
|
|
31
|
+
git grep -i "TESTUS00" # should return tests/fixtures/example.yaml
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
If the real terms return any matches, **stop**. Do not push. Remove the
|
|
35
|
+
leaked data and re-run.
|
|
36
|
+
|
|
37
|
+
## Release steps
|
|
38
|
+
|
|
39
|
+
1. Update `CHANGELOG.md` — move `[Unreleased]` entries under a new
|
|
40
|
+
`[X.Y.Z] - YYYY-MM-DD` section.
|
|
41
|
+
2. Bump version in `pyproject.toml`.
|
|
42
|
+
3. Commit + tag: `git commit -am "Release vX.Y.Z" && git tag vX.Y.Z`.
|
|
43
|
+
4. Push: `git push && git push --tags`.
|
|
44
|
+
5. Build: `uv build` (or `python -m build`).
|
|
45
|
+
6. Publish: `uv publish` (or `twine upload dist/*`).
|
|
46
|
+
7. Verify the package landed on PyPI: https://pypi.org/project/yinv/
|
|
47
|
+
|
|
48
|
+
## Homebrew formula (first release only)
|
|
49
|
+
|
|
50
|
+
1. Generate resource blocks from PyPI:
|
|
51
|
+
```sh
|
|
52
|
+
pipx run homebrew-pypi-poet -f yinv
|
|
53
|
+
```
|
|
54
|
+
2. Create a personal tap repo on GitHub: `homebrew-yinv`.
|
|
55
|
+
3. Add `Formula/yinv.rb`:
|
|
56
|
+
```ruby
|
|
57
|
+
class Yinv < Formula
|
|
58
|
+
include Language::Python::Virtualenv
|
|
59
|
+
|
|
60
|
+
desc "CLI to generate monthly consulting invoices as PDFs"
|
|
61
|
+
homepage "https://github.com/<user>/invoiceGenerator"
|
|
62
|
+
url "https://files.pythonhosted.org/packages/source/y/yinv/yinv-X.Y.Z.tar.gz"
|
|
63
|
+
sha256 "<sha from PyPI>"
|
|
64
|
+
license "MIT"
|
|
65
|
+
|
|
66
|
+
depends_on "pango"
|
|
67
|
+
depends_on "gdk-pixbuf"
|
|
68
|
+
depends_on "libffi"
|
|
69
|
+
depends_on "python@3.12"
|
|
70
|
+
|
|
71
|
+
# <resource blocks from homebrew-pypi-poet output>
|
|
72
|
+
|
|
73
|
+
def install
|
|
74
|
+
virtualenv_install_with_resources
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
test do
|
|
78
|
+
assert_match "yinv", shell_output("#{bin}/yinv --help")
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
```
|
|
82
|
+
4. Commit and push the tap.
|
|
83
|
+
5. Install from the tap:
|
|
84
|
+
```sh
|
|
85
|
+
brew tap <user>/yinv
|
|
86
|
+
brew install yinv
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Subsequent releases
|
|
90
|
+
|
|
91
|
+
1. Do the privacy audit again (secrets can accumulate over time).
|
|
92
|
+
2. Update `CHANGELOG.md`, bump version, tag, push, `uv build && uv publish`.
|
|
93
|
+
3. In the tap repo, update `url`, `sha256`, and re-run
|
|
94
|
+
`homebrew-pypi-poet -f yinv` to refresh the resource blocks.
|
|
95
|
+
4. Commit the updated formula, push the tap.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "yinv"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "CLI to generate monthly consulting invoices as PDFs from YAML"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { file = "LICENSE" }
|
|
11
|
+
requires-python = ">=3.11"
|
|
12
|
+
authors = [{ name = "Nicolas Maldonado" }]
|
|
13
|
+
keywords = ["invoice", "pdf", "yaml", "cli", "billing"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: End Users/Desktop",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: MacOS",
|
|
20
|
+
"Operating System :: POSIX :: Linux",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Topic :: Office/Business",
|
|
25
|
+
]
|
|
26
|
+
dependencies = [
|
|
27
|
+
"PyYAML>=6.0",
|
|
28
|
+
"Jinja2>=3.1",
|
|
29
|
+
"weasyprint>=60.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
dev = [
|
|
34
|
+
"pytest>=8.0",
|
|
35
|
+
"build>=1.0",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[project.scripts]
|
|
39
|
+
yinv = "yinv.cli:main"
|
|
40
|
+
|
|
41
|
+
[tool.hatch.build.targets.wheel]
|
|
42
|
+
packages = ["src/yinv"]
|
|
43
|
+
|
|
44
|
+
[tool.hatch.build.targets.sdist]
|
|
45
|
+
include = [
|
|
46
|
+
"/src",
|
|
47
|
+
"/tests",
|
|
48
|
+
"/README.md",
|
|
49
|
+
"/LICENSE",
|
|
50
|
+
"/CHANGELOG.md",
|
|
51
|
+
"/RELEASING.md",
|
|
52
|
+
"/pyproject.toml",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
[tool.pytest.ini_options]
|
|
56
|
+
testpaths = ["tests"]
|
|
57
|
+
pythonpath = ["src"]
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""yinv — YAML-driven monthly invoice generator."""
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
__version__ = version("yinv")
|
|
7
|
+
except PackageNotFoundError: # package is not installed (e.g. running from source)
|
|
8
|
+
__version__ = "0.0.0+unknown"
|
|
9
|
+
|
|
10
|
+
__all__ = ["__version__"]
|