pdfly 0.3.0__tar.gz → 0.3.1__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 (58) hide show
  1. {pdfly-0.3.0 → pdfly-0.3.1}/.github/workflows/github-ci.yaml +1 -1
  2. {pdfly-0.3.0 → pdfly-0.3.1}/.github/workflows/release.yaml +31 -3
  3. {pdfly-0.3.0 → pdfly-0.3.1}/.gitignore +4 -0
  4. {pdfly-0.3.0 → pdfly-0.3.1}/.pre-commit-config.yaml +3 -1
  5. {pdfly-0.3.0 → pdfly-0.3.1}/CHANGELOG.md +12 -0
  6. {pdfly-0.3.0 → pdfly-0.3.1}/Makefile +4 -0
  7. {pdfly-0.3.0 → pdfly-0.3.1}/PKG-INFO +1 -1
  8. pdfly-0.3.1/make_release.py +377 -0
  9. pdfly-0.3.1/pdfly/_version.py +1 -0
  10. {pdfly-0.3.0 → pdfly-0.3.1}/pdfly/up2.py +1 -1
  11. {pdfly-0.3.0 → pdfly-0.3.1}/pyproject.toml +1 -0
  12. {pdfly-0.3.0 → pdfly-0.3.1}/requirements/dev.in +2 -0
  13. {pdfly-0.3.0 → pdfly-0.3.1}/requirements/dev.txt +12 -1
  14. pdfly-0.3.0/pdfly/_version.py +0 -1
  15. {pdfly-0.3.0 → pdfly-0.3.1}/.github/dependabot.yml +0 -0
  16. {pdfly-0.3.0 → pdfly-0.3.1}/.gitmodules +0 -0
  17. {pdfly-0.3.0 → pdfly-0.3.1}/.isort.cfg +0 -0
  18. {pdfly-0.3.0 → pdfly-0.3.1}/.readthedocs.yaml +0 -0
  19. {pdfly-0.3.0 → pdfly-0.3.1}/CONTRIBUTORS.md +0 -0
  20. {pdfly-0.3.0 → pdfly-0.3.1}/LICENSE +0 -0
  21. {pdfly-0.3.0 → pdfly-0.3.1}/README.md +0 -0
  22. {pdfly-0.3.0 → pdfly-0.3.1}/docs/Makefile +0 -0
  23. {pdfly-0.3.0 → pdfly-0.3.1}/docs/conf.py +0 -0
  24. {pdfly-0.3.0 → pdfly-0.3.1}/docs/index.rst +0 -0
  25. {pdfly-0.3.0 → pdfly-0.3.1}/docs/make.bat +0 -0
  26. {pdfly-0.3.0 → pdfly-0.3.1}/docs/meta/project-governance.md +0 -0
  27. {pdfly-0.3.0 → pdfly-0.3.1}/docs/user/installation.md +0 -0
  28. {pdfly-0.3.0 → pdfly-0.3.1}/docs/user/subcommand-cat.md +0 -0
  29. {pdfly-0.3.0 → pdfly-0.3.1}/docs/user/subcommand-meta.md +0 -0
  30. {pdfly-0.3.0 → pdfly-0.3.1}/docs/user/subcommand-x2pdf.md +0 -0
  31. {pdfly-0.3.0 → pdfly-0.3.1}/mypy.ini +0 -0
  32. {pdfly-0.3.0 → pdfly-0.3.1}/pdfly/__init__.py +0 -0
  33. {pdfly-0.3.0 → pdfly-0.3.1}/pdfly/__main__.py +0 -0
  34. {pdfly-0.3.0 → pdfly-0.3.1}/pdfly/_utils.py +0 -0
  35. {pdfly-0.3.0 → pdfly-0.3.1}/pdfly/cat.py +0 -0
  36. {pdfly-0.3.0 → pdfly-0.3.1}/pdfly/cli.py +0 -0
  37. {pdfly-0.3.0 → pdfly-0.3.1}/pdfly/compress.py +0 -0
  38. {pdfly-0.3.0 → pdfly-0.3.1}/pdfly/extract_images.py +0 -0
  39. {pdfly-0.3.0 → pdfly-0.3.1}/pdfly/metadata.py +0 -0
  40. {pdfly-0.3.0 → pdfly-0.3.1}/pdfly/pagemeta.py +0 -0
  41. {pdfly-0.3.0 → pdfly-0.3.1}/pdfly/x2pdf.py +0 -0
  42. {pdfly-0.3.0 → pdfly-0.3.1}/requirements/ci.in +0 -0
  43. {pdfly-0.3.0 → pdfly-0.3.1}/requirements/ci.txt +0 -0
  44. {pdfly-0.3.0 → pdfly-0.3.1}/requirements/docs.in +0 -0
  45. {pdfly-0.3.0 → pdfly-0.3.1}/requirements/docs.txt +0 -0
  46. {pdfly-0.3.0 → pdfly-0.3.1}/resources/GeoBase_NHNC1_Data_Model_UML_EN.pdf +0 -0
  47. {pdfly-0.3.0 → pdfly-0.3.1}/resources/baleines.jpg +0 -0
  48. {pdfly-0.3.0 → pdfly-0.3.1}/resources/box.pdf +0 -0
  49. {pdfly-0.3.0 → pdfly-0.3.1}/resources/jpeg.pdf +0 -0
  50. {pdfly-0.3.0 → pdfly-0.3.1}/resources/pythonknight.png +0 -0
  51. {pdfly-0.3.0 → pdfly-0.3.1}/setup.cfg +0 -0
  52. {pdfly-0.3.0 → pdfly-0.3.1}/setup.py +0 -0
  53. {pdfly-0.3.0 → pdfly-0.3.1}/tests/__init__.py +0 -0
  54. {pdfly-0.3.0 → pdfly-0.3.1}/tests/conftest.py +0 -0
  55. {pdfly-0.3.0 → pdfly-0.3.1}/tests/test_cat.py +0 -0
  56. {pdfly-0.3.0 → pdfly-0.3.1}/tests/test_cli.py +0 -0
  57. {pdfly-0.3.0 → pdfly-0.3.1}/tests/test_extract_images.py +0 -0
  58. {pdfly-0.3.0 → pdfly-0.3.1}/tests/test_x2pdf.py +0 -0
@@ -54,7 +54,7 @@ jobs:
54
54
  submodules: 'recursive'
55
55
  - name: Cache Downloaded Files
56
56
  id: cache-downloaded-files
57
- uses: actions/cache@v3
57
+ uses: actions/cache@v4
58
58
  with:
59
59
  path: '**/tests/pdf_cache/*'
60
60
  key: cache-downloaded-files
@@ -6,19 +6,47 @@
6
6
  name: Publish Python Package to PyPI
7
7
  on:
8
8
  push:
9
- tags:
10
- - '*.*.*'
9
+ branches:
10
+ - main
11
+
12
+ permissions:
13
+ contents: write
11
14
 
12
15
  jobs:
13
16
  build_and_publish:
14
17
  name: Publish a new version
15
18
  runs-on: ubuntu-latest
16
-
19
+ if: "${{ startsWith(github.event.head_commit.message, 'REL: ') }}"
17
20
  steps:
18
21
  # Ensure it's on PyPI
19
22
  - name: Checkout Repository
20
23
  uses: actions/checkout@v4
21
24
 
25
+ - name: Extract version from commit message
26
+ id: extract_version
27
+ run: |
28
+ VERSION=$(echo "${{ github.event.head_commit.message }}" | grep -oP '(?<=REL: )\d+\.\d+\.\d+')
29
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
30
+
31
+ - name: Extract tag message from commit message
32
+ id: extract_message
33
+ run: |
34
+ VERSION="${{ steps.extract_version.outputs.version }}"
35
+ delimiter="$(openssl rand -hex 8)"
36
+ MESSAGE=$(echo "${{ github.event.head_commit.message }}" | sed "0,/REL: $VERSION/s///" )
37
+ echo "message<<${delimiter}" >> $GITHUB_OUTPUT
38
+ echo "$MESSAGE" >> $GITHUB_OUTPUT
39
+ echo "${delimiter}" >> $GITHUB_OUTPUT
40
+
41
+ - name: Create Git Tag
42
+ run: |
43
+ VERSION="${{ steps.extract_version.outputs.version }}"
44
+ MESSAGE="${{ steps.extract_message.outputs.message }}"
45
+ git config user.name github-actions
46
+ git config user.email github-actions@github.com
47
+ git tag "$VERSION" -m "$MESSAGE"
48
+ git push origin $VERSION
49
+
22
50
  - name: Set up Python
23
51
  uses: actions/setup-python@v5
24
52
  with:
@@ -134,3 +134,7 @@ dmypy.json
134
134
  # Documentation files copied when building:
135
135
  docs/meta/CHANGELOG.md
136
136
  docs/meta/CONTRIBUTORS.md
137
+
138
+ # 'make release' creates those files:
139
+ RELEASE_COMMIT_MSG.md
140
+ RELEASE_TAG_MSG.md
@@ -48,5 +48,7 @@ repos:
48
48
  rev: 'v1.7.1'
49
49
  hooks:
50
50
  - id: mypy
51
- files: ^pypdf/.*
51
+ files: ^pdfly/.*
52
52
  args: [--ignore-missing-imports]
53
+ additional_dependencies:
54
+ - "pydantic>=1.10.4"
@@ -1,5 +1,17 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## Version 0.3.1, 2024-03-29
4
+
5
+ ### Maintenance (MAINT)
6
+ - Update pypdf usage (#48)
7
+
8
+ ### Developer Experience (DEV)
9
+ - Release via REL commit (#48)
10
+ - Fix mypy issues
11
+ - Add make_release.py
12
+
13
+ [Full Changelog](https://github.com/py-pdf/pdfly/compare/0.3.0...0.3.1)
14
+
3
15
  ## Version 0.3.0, 2023-12-17
4
16
 
5
17
  ### New Features (ENH)
@@ -4,6 +4,10 @@ maint:
4
4
  pip-compile -U requirements/dev.in
5
5
  pip-compile -U requirements/docs.in
6
6
 
7
+ release:
8
+ python make_release.py
9
+ git commit -eF RELEASE_COMMIT_MSG.md
10
+
7
11
  upload:
8
12
  make clean
9
13
  flit publish
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pdfly
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: A pure-python CLI application to manipulate PDF files
5
5
  Author-email: Martin Thoma <info@martin-thoma.de>
6
6
  Maintainer-email: Martin Thoma <info@martin-thoma.de>
@@ -0,0 +1,377 @@
1
+ """Internal tool to update the changelog."""
2
+
3
+ import json
4
+ import subprocess
5
+ import urllib.request
6
+ from dataclasses import dataclass
7
+ from datetime import datetime, timezone
8
+ from typing import Any, Dict, List, Tuple
9
+
10
+ from rich.prompt import Prompt
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class Change:
15
+ """Capture the data of a git commit."""
16
+
17
+ commit_hash: str
18
+ prefix: str
19
+ message: str
20
+ author: str
21
+ author_login: str
22
+
23
+
24
+ def main(changelog_path: str) -> None:
25
+ """
26
+ Create a changelog.
27
+
28
+ Args:
29
+ changelog_path: The location of the CHANGELOG file
30
+ """
31
+ changelog = get_changelog(changelog_path)
32
+ git_tag = get_most_recent_git_tag()
33
+ changes, changes_with_author = get_formatted_changes(git_tag)
34
+ if changes == "":
35
+ print("No changes")
36
+ return
37
+
38
+ new_version = version_bump(git_tag)
39
+ new_version = get_version_interactive(new_version, changes)
40
+ adjust_version_py(new_version)
41
+
42
+ today = datetime.now(tz=timezone.utc)
43
+ header = f"## Version {new_version}, {today:%Y-%m-%d}\n"
44
+ url = f"https://github.com/py-pdf/pdfly/compare/{git_tag}...{new_version}"
45
+ trailer = f"\n[Full Changelog]({url})\n\n"
46
+ new_entry = header + changes + trailer
47
+ print(new_entry)
48
+ write_commit_msg_file(new_version, changes_with_author + trailer)
49
+ write_release_msg_file(new_version, changes_with_author + trailer, today)
50
+
51
+ # Make the script idempotent by checking if the new entry is already in the changelog
52
+ if new_entry in changelog:
53
+ print("Changelog is already up-to-date!")
54
+ return
55
+
56
+ new_changelog = "# CHANGELOG\n\n" + new_entry + strip_header(changelog)
57
+ write_changelog(new_changelog, changelog_path)
58
+ print_instructions(new_version)
59
+
60
+
61
+ def print_instructions(new_version: str) -> None:
62
+ """Print release instructions."""
63
+ print("=" * 80)
64
+ print(f"☑ _version.py was adjusted to '{new_version}'")
65
+ print("☑ CHANGELOG.md was adjusted")
66
+ print("")
67
+ print("Now run:")
68
+ print(" git commit -eF RELEASE_COMMIT_MSG.md")
69
+ print(f" git tag -s {new_version} -eF RELEASE_TAG_MSG.md")
70
+ print(" git push")
71
+ print(" git push --tags")
72
+
73
+
74
+ def adjust_version_py(version: str) -> None:
75
+ """Adjust the __version__ string."""
76
+ with open("pdfly/_version.py", "w") as fp:
77
+ fp.write(f'__version__ = "{version}"\n')
78
+
79
+
80
+ def get_version_interactive(new_version: str, changes: str) -> str:
81
+ """Get the new __version__ interactively."""
82
+ print("The changes are:")
83
+ print(changes)
84
+ orig = new_version
85
+ new_version = Prompt.ask("New semantic version", default=orig)
86
+ while not is_semantic_version(new_version):
87
+ new_version = Prompt.ask(
88
+ "That was not a semantic version. Please enter a semantic version",
89
+ default=orig,
90
+ )
91
+ return new_version
92
+
93
+
94
+ def is_semantic_version(version: str) -> bool:
95
+ """Check if the given version is a semantic version."""
96
+ # It's not so important to cover the edge-cases like pre-releases
97
+ # This is meant for pdfly only and we don't make pre-releases
98
+ if version.count(".") != 2:
99
+ return False
100
+ try:
101
+ return bool([int(part) for part in version.split(".")])
102
+ except Exception:
103
+ return False
104
+
105
+
106
+ def write_commit_msg_file(new_version: str, commit_changes: str) -> None:
107
+ """
108
+ Write a file that can be used as a commit message.
109
+
110
+ Like this:
111
+
112
+ git commit -eF RELEASE_COMMIT_MSG.md && git push
113
+ """
114
+ with open("RELEASE_COMMIT_MSG.md", "w") as fp:
115
+ fp.write(f"REL: {new_version}\n\n")
116
+ fp.write("## What's new\n")
117
+ fp.write(commit_changes)
118
+
119
+
120
+ def write_release_msg_file(
121
+ new_version: str, commit_changes: str, today: datetime
122
+ ) -> None:
123
+ """
124
+ Write a file that can be used as a git tag message.
125
+
126
+ Like this:
127
+
128
+ git tag -eF RELEASE_TAG_MSG.md && git push
129
+ """
130
+ with open("RELEASE_TAG_MSG.md", "w") as fp:
131
+ fp.write(f"Version {new_version}, {today:%Y-%m-%d}\n\n")
132
+ fp.write("## What's new\n")
133
+ fp.write(commit_changes)
134
+
135
+
136
+ def strip_header(md: str) -> str:
137
+ """Remove the 'CHANGELOG' header."""
138
+ return md.lstrip("# CHANGELOG").lstrip() # noqa
139
+
140
+
141
+ def version_bump(git_tag: str) -> str:
142
+ """
143
+ Increase the patch version of the git tag by one.
144
+
145
+ Args:
146
+ git_tag: Old version tag
147
+
148
+ Returns:
149
+ The new version where the patch version is bumped.
150
+ """
151
+ # just assume a patch version change
152
+ major, minor, patch = git_tag.split(".")
153
+ return f"{major}.{minor}.{int(patch) + 1}"
154
+
155
+
156
+ def get_changelog(changelog_path: str) -> str:
157
+ """
158
+ Read the changelog.
159
+
160
+ Args:
161
+ changelog_path: Path to the CHANGELOG file
162
+
163
+ Returns:
164
+ Data of the CHANGELOG
165
+ """
166
+ with open(changelog_path) as fh:
167
+ changelog = fh.read()
168
+ return changelog
169
+
170
+
171
+ def write_changelog(new_changelog: str, changelog_path: str) -> None:
172
+ """
173
+ Write the changelog.
174
+
175
+ Args:
176
+ new_changelog: Contents of the new CHANGELOG
177
+ changelog_path: Path where the CHANGELOG file is
178
+ """
179
+ with open(changelog_path, "w") as fh:
180
+ fh.write(new_changelog)
181
+
182
+
183
+ def get_formatted_changes(git_tag: str) -> Tuple[str, str]:
184
+ """
185
+ Format the changes done since the last tag.
186
+
187
+ Args:
188
+ git_tag: the reference tag
189
+
190
+ Returns:
191
+ Changes done since git_tag
192
+ """
193
+ commits = get_git_commits_since_tag(git_tag)
194
+
195
+ # Group by prefix
196
+ grouped: Dict[str, List[Dict[str, Any]]] = {}
197
+ for commit in commits:
198
+ if commit.prefix not in grouped:
199
+ grouped[commit.prefix] = []
200
+ grouped[commit.prefix].append(
201
+ {"msg": commit.message, "author": commit.author_login}
202
+ )
203
+
204
+ # Order prefixes
205
+ order = [
206
+ "SEC",
207
+ "DEP",
208
+ "ENH",
209
+ "PI",
210
+ "BUG",
211
+ "ROB",
212
+ "DOC",
213
+ "DEV",
214
+ "CI",
215
+ "MAINT",
216
+ "TST",
217
+ "STY",
218
+ ]
219
+ abbrev2long = {
220
+ "SEC": "Security",
221
+ "DEP": "Deprecations",
222
+ "ENH": "New Features",
223
+ "BUG": "Bug Fixes",
224
+ "ROB": "Robustness",
225
+ "DOC": "Documentation",
226
+ "DEV": "Developer Experience",
227
+ "CI": "Continuous Integration",
228
+ "MAINT": "Maintenance",
229
+ "TST": "Testing",
230
+ "STY": "Code Style",
231
+ "PI": "Performance Improvements",
232
+ }
233
+
234
+ # Create output
235
+ output = ""
236
+ output_with_user = ""
237
+ for prefix in order:
238
+ if prefix not in grouped:
239
+ continue
240
+ tmp = f"\n### {abbrev2long[prefix]} ({prefix})\n" # header
241
+ output += tmp
242
+ output_with_user += tmp
243
+ for commit_dict in grouped[prefix]:
244
+ output += f"- {commit_dict['msg']}\n"
245
+ output_with_user += (
246
+ f"- {commit_dict['msg']} by @{commit_dict['author']}\n"
247
+ )
248
+ del grouped[prefix]
249
+
250
+ if grouped:
251
+ output += "\n### Other\n"
252
+ for prefix in grouped:
253
+ output += f"- {prefix}: {grouped[prefix]}\n"
254
+
255
+ return output, output_with_user
256
+
257
+
258
+ def get_most_recent_git_tag() -> str:
259
+ """
260
+ Get the git tag most recently created.
261
+
262
+ Returns:
263
+ Most recently created git tag.
264
+ """
265
+ git_tag = str(
266
+ subprocess.check_output(
267
+ ["git", "describe", "--abbrev=0"], stderr=subprocess.STDOUT
268
+ )
269
+ ).strip("'b\\n")
270
+ return git_tag
271
+
272
+
273
+ def get_author_mapping(line_count: int) -> Dict[str, str]:
274
+ """
275
+ Get the authors for each commit.
276
+
277
+ Args:
278
+ line_count: Number of lines from Git log output. Used for determining how
279
+ many commits to fetch.
280
+
281
+ Returns:
282
+ A mapping of long commit hashes to author login handles.
283
+ """
284
+ per_page = min(line_count, 100)
285
+ page = 1
286
+ mapping: Dict[str, str] = {}
287
+ for _ in range(0, line_count, per_page):
288
+ with urllib.request.urlopen( # noqa: S310
289
+ f"https://api.github.com/repos/py-pdf/pdfly/commits?per_page={per_page}&page={page}"
290
+ ) as response:
291
+ commits = json.loads(response.read())
292
+ page += 1
293
+ for commit in commits:
294
+ print(commit)
295
+ if commit["author"]:
296
+ gh_handle = commit["author"]["login"]
297
+ else:
298
+ # This is not perfect, but better than the other option
299
+ gh_handle = commit["commit"]["author"]["name"].replace(" ", "")
300
+ mapping[commit["sha"]] = gh_handle
301
+ return mapping
302
+
303
+
304
+ def get_git_commits_since_tag(git_tag: str) -> List[Change]:
305
+ """
306
+ Get all commits since the last tag.
307
+
308
+ Args:
309
+ git_tag: Reference tag from which the changes to the current commit are
310
+ fetched.
311
+
312
+ Returns:
313
+ List of all changes since git_tag.
314
+ """
315
+ commits = str(
316
+ subprocess.check_output(
317
+ [
318
+ "git",
319
+ "--no-pager",
320
+ "log",
321
+ f"{git_tag}..HEAD",
322
+ '--pretty=format:"%H:::%s:::%aN"',
323
+ ],
324
+ stderr=subprocess.STDOUT,
325
+ )
326
+ ).strip("'b\\n")
327
+ lines = commits.split("\\n")
328
+ authors = get_author_mapping(len(lines))
329
+ return [parse_commit_line(line, authors) for line in lines if line != ""]
330
+
331
+
332
+ def parse_commit_line(line: str, authors: Dict[str, str]) -> Change:
333
+ """
334
+ Parse the first line of a git commit message.
335
+
336
+ Args:
337
+ line: The first line of a git commit message.
338
+
339
+ Returns:
340
+ The parsed Change object
341
+
342
+ Raises:
343
+ ValueError: The commit line is not well-structured
344
+ """
345
+ parts = line.split(":::")
346
+ if len(parts) != 3:
347
+ raise ValueError(f"Invalid commit line: '{line}'")
348
+ commit_hash, rest, author = parts
349
+ if ":" in rest:
350
+ prefix, message = rest.split(":", 1)
351
+ else:
352
+ prefix = ""
353
+ message = rest
354
+
355
+ # Standardize
356
+ message.strip()
357
+ commit_hash = commit_hash.strip('"')
358
+
359
+ if author.endswith('"'):
360
+ author = author[:-1]
361
+ author_login = authors[commit_hash]
362
+
363
+ prefix = prefix.strip()
364
+ if prefix == "DOCS":
365
+ prefix = "DOC"
366
+
367
+ return Change(
368
+ commit_hash=commit_hash,
369
+ prefix=prefix,
370
+ message=message,
371
+ author=author,
372
+ author_login=author_login,
373
+ )
374
+
375
+
376
+ if __name__ == "__main__":
377
+ main("CHANGELOG.md")
@@ -0,0 +1 @@
1
+ __version__ = "0.3.1"
@@ -18,7 +18,7 @@ def main(pdf: Path, output: Path) -> None:
18
18
  for i in range(0, len(reader.pages) - 1, 2):
19
19
  lhs = reader.pages[i]
20
20
  rhs = reader.pages[i + 1]
21
- lhs.mergeTranslatedPage(rhs, float(lhs.mediabox.right), 0, True)
21
+ lhs.merge_translated_page(rhs, float(lhs.mediabox.right), 0, True)
22
22
  writer.add_page(lhs)
23
23
  print(str(i) + " ")
24
24
  sys.stdout.flush()
@@ -143,3 +143,4 @@ max-complexity = 20 # Recommended: 10
143
143
 
144
144
  [tool.ruff.per-file-ignores]
145
145
  "sample-files/*" = ["D100", "INP001", "FA102", "I001"]
146
+ "make_release.py" = ["T201", "S603", "S607"]
@@ -1,9 +1,11 @@
1
1
  black
2
2
  pip-tools
3
3
  pre-commit>=3.2.0
4
+ pydantic
4
5
  pytest
5
6
  pytest-cov
6
7
  pytest-socket
7
8
  pytest-timeout
9
+ rich
8
10
  twine
9
11
  wheel
@@ -8,6 +8,8 @@ aiohttp==3.9.1
8
8
  # via black
9
9
  aiosignal==1.3.1
10
10
  # via aiohttp
11
+ annotated-types==0.6.0
12
+ # via pydantic
11
13
  async-timeout==4.0.3
12
14
  # via aiohttp
13
15
  attrs==23.1.0
@@ -106,6 +108,10 @@ pre-commit==3.5.0
106
108
  # via -r requirements/dev.in
107
109
  pycparser==2.21
108
110
  # via cffi
111
+ pydantic==2.5.2
112
+ # via -r requirements/dev.in
113
+ pydantic-core==2.14.5
114
+ # via pydantic
109
115
  pygments==2.17.2
110
116
  # via
111
117
  # readme-renderer
@@ -137,7 +143,9 @@ requests-toolbelt==1.0.0
137
143
  rfc3986==2.0.0
138
144
  # via twine
139
145
  rich==13.7.0
140
- # via twine
146
+ # via
147
+ # -r requirements/dev.in
148
+ # twine
141
149
  secretstorage==3.3.3
142
150
  # via keyring
143
151
  tomli==2.0.1
@@ -152,7 +160,10 @@ twine==4.0.2
152
160
  # via -r requirements/dev.in
153
161
  typing-extensions==4.9.0
154
162
  # via
163
+ # annotated-types
155
164
  # black
165
+ # pydantic
166
+ # pydantic-core
156
167
  # rich
157
168
  urllib3==2.1.0
158
169
  # via
@@ -1 +0,0 @@
1
- __version__ = "0.3.0"
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
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