PyCheval 0.2.0__tar.gz → 0.2.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.
- {pycheval-0.2.0 → pycheval-0.2.2}/PKG-INFO +5 -4
- {pycheval-0.2.0 → pycheval-0.2.2}/pyproject.toml +11 -9
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/model.py +1 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/pdf_embed.py +23 -13
- {pycheval-0.2.0 → pycheval-0.2.2}/LICENSE +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/README.md +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/__init__.py +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/_locale.py +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/_test_data.py +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/const.py +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/countries.py +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/exc.py +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/format.py +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/generate.py +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/locale/de/LC_MESSAGES/pycheval.mo +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/locale/de/LC_MESSAGES/pycheval.po +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/money.py +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/parse.py +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/pdf_common.py +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/pdf_extract.py +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/pdf_parse.py +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/py.typed +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/quantities.py +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/type_codes.py +0 -0
- {pycheval-0.2.0 → pycheval-0.2.2}/src/pycheval/types.py +0 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: PyCheval
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Factur-X/ZUGFeRD parsing and generation library for Python
|
|
5
|
-
License: Apache-2.0
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
License-File: LICENSE
|
|
6
7
|
Keywords: factur-x,zugferd,invoice,billing
|
|
7
8
|
Author: Sebastian Rittau
|
|
8
9
|
Author-email: sebastian.rittau@zfutura.de
|
|
@@ -11,7 +12,7 @@ Classifier: Development Status :: 3 - Alpha
|
|
|
11
12
|
Classifier: Intended Audience :: Developers
|
|
12
13
|
Classifier: Topic :: File Formats
|
|
13
14
|
Classifier: Topic :: Office/Business :: Financial :: Accounting
|
|
14
|
-
Requires-Dist: pypdf (>=
|
|
15
|
+
Requires-Dist: pypdf (>=6.1.1,<7)
|
|
15
16
|
Project-URL: GitHub, https://github.com/zfutura/pycheval
|
|
16
17
|
Description-Content-Type: text/markdown
|
|
17
18
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "PyCheval"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.2"
|
|
4
4
|
description = "Factur-X/ZUGFeRD parsing and generation library for Python"
|
|
5
5
|
authors = [{ name = "Sebastian Rittau", email = "sebastian.rittau@zfutura.de" }]
|
|
6
6
|
readme = "README.md"
|
|
@@ -14,23 +14,25 @@ classifiers = [
|
|
|
14
14
|
]
|
|
15
15
|
requires-python = ">= 3.11"
|
|
16
16
|
dependencies = [
|
|
17
|
-
"pypdf >=
|
|
17
|
+
"pypdf >= 6.1.1, < 7",
|
|
18
18
|
]
|
|
19
19
|
|
|
20
20
|
[project.urls]
|
|
21
21
|
GitHub = "https://github.com/zfutura/pycheval"
|
|
22
22
|
|
|
23
|
+
[dependency-groups]
|
|
24
|
+
dev = [
|
|
25
|
+
"babel >= 2.17.0, < 3",
|
|
26
|
+
"mypy ~= 1.18.2",
|
|
27
|
+
"poethepoet ~= 0.37.0",
|
|
28
|
+
"pytest >= 8.4.2, < 9",
|
|
29
|
+
"ruff ~= 0.14.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
23
32
|
[tool.poetry]
|
|
24
33
|
include = [{ path = "src/pycheval/locale/**/*.mo", format = ["sdist", "wheel"] }]
|
|
25
34
|
exclude = ["src/pycheval/test_*"]
|
|
26
35
|
|
|
27
|
-
[tool.poetry.group.dev.dependencies]
|
|
28
|
-
babel = "~=2.17.0"
|
|
29
|
-
mypy = "~=1.17.0"
|
|
30
|
-
poethepoet = "^0.36.0"
|
|
31
|
-
pytest = "^8.4.1"
|
|
32
|
-
ruff = "^0.12.1"
|
|
33
|
-
|
|
34
36
|
[tool.poe.tasks.lint]
|
|
35
37
|
cmd = "ruff check src"
|
|
36
38
|
help = "Lint the source code with ruff"
|
|
@@ -462,6 +462,7 @@ class BasicInvoice(BasicWLInvoice):
|
|
|
462
462
|
line_items: Sequence[LineItem] # BG-25
|
|
463
463
|
|
|
464
464
|
def __post_init__(self) -> None:
|
|
465
|
+
super().__post_init__()
|
|
465
466
|
if len(self.line_items) < 1:
|
|
466
467
|
raise ModelError("At least one line item is required.")
|
|
467
468
|
if type(self) is BasicInvoice:
|
|
@@ -10,6 +10,7 @@ from pypdf import PdfWriter
|
|
|
10
10
|
from pypdf.generic import (
|
|
11
11
|
ArrayObject,
|
|
12
12
|
DictionaryObject,
|
|
13
|
+
IndirectObject,
|
|
13
14
|
NameObject,
|
|
14
15
|
create_string_object,
|
|
15
16
|
)
|
|
@@ -192,22 +193,31 @@ def _add_attachment(
|
|
|
192
193
|
# Replace file dictionary with an indirect object.
|
|
193
194
|
catalog = writer._root_object
|
|
194
195
|
names_dict = catalog["/Names"]
|
|
195
|
-
assert isinstance(names_dict, DictionaryObject)
|
|
196
|
+
assert isinstance(names_dict, DictionaryObject), (
|
|
197
|
+
f"/Names is {type(names_dict)}"
|
|
198
|
+
)
|
|
196
199
|
embedded_files = names_dict["/EmbeddedFiles"]
|
|
197
|
-
assert isinstance(embedded_files, DictionaryObject)
|
|
200
|
+
assert isinstance(embedded_files, DictionaryObject), (
|
|
201
|
+
f"/EmbeddedFiles is {type(embedded_files)}"
|
|
202
|
+
)
|
|
198
203
|
names_array = embedded_files["/Names"]
|
|
199
|
-
assert isinstance(names_array, ArrayObject)
|
|
204
|
+
assert isinstance(names_array, ArrayObject), (
|
|
205
|
+
f"/Names is {type(names_array)}"
|
|
206
|
+
)
|
|
200
207
|
file_dict = names_array[-1]
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
208
|
+
if not isinstance(file_dict, IndirectObject):
|
|
209
|
+
assert isinstance(file_dict, DictionaryObject), (
|
|
210
|
+
f"file_dict is {type(file_dict)}"
|
|
211
|
+
)
|
|
212
|
+
file_ref = writer._add_object(file_dict)
|
|
213
|
+
names_array[-1] = file_ref
|
|
214
|
+
|
|
215
|
+
# Add the file reference to the /AF array in the catalog.
|
|
216
|
+
if NameObject("/AF") not in catalog:
|
|
217
|
+
catalog[NameObject("/AF")] = ArrayObject()
|
|
218
|
+
af_array = catalog[NameObject("/AF")]
|
|
219
|
+
assert isinstance(af_array, ArrayObject), f"/AF is {type(af_array)}"
|
|
220
|
+
af_array.append(file_ref)
|
|
211
221
|
|
|
212
222
|
|
|
213
223
|
def main() -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|