pdflinkcheck 1.1.73__py3-none-any.whl → 1.2.29__py3-none-any.whl

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 (186) hide show
  1. pdflinkcheck/__init__.py +88 -21
  2. pdflinkcheck/__main__.py +6 -0
  3. pdflinkcheck/analysis_pdfium.py +131 -0
  4. pdflinkcheck/{analyze_pymupdf.py → analysis_pymupdf.py} +109 -145
  5. pdflinkcheck/{analyze_pypdf.py → analysis_pypdf.py} +67 -37
  6. pdflinkcheck/cli.py +111 -116
  7. pdflinkcheck/data/I Have Questions.md +51 -0
  8. pdflinkcheck/data/LICENSE +20 -654
  9. pdflinkcheck/data/README.md +65 -67
  10. pdflinkcheck/data/icons/BoxArt-1080x1080.png +0 -0
  11. pdflinkcheck/data/icons/Logo-150x150.png +0 -0
  12. pdflinkcheck/data/icons/Logo-300x300.png +0 -0
  13. pdflinkcheck/data/icons/Logo-71x71.png +0 -0
  14. pdflinkcheck/data/icons/PosterArt-720x1080.png +0 -0
  15. pdflinkcheck/data/icons/SmallLogo-44x44.png +0 -0
  16. pdflinkcheck/data/icons/SplashScreen-620x300.png +0 -0
  17. pdflinkcheck/data/icons/StoreLogo-50x50.png +0 -0
  18. pdflinkcheck/data/icons/WideLogo-310x150.png +0 -0
  19. pdflinkcheck/data/icons/red_pdf_512px.ico +0 -0
  20. pdflinkcheck/data/pyproject.toml +25 -37
  21. pdflinkcheck/data/themes/forest/forest-dark/border-accent-hover.png +0 -0
  22. pdflinkcheck/data/themes/forest/forest-dark/border-accent.png +0 -0
  23. pdflinkcheck/data/themes/forest/forest-dark/border-basic.png +0 -0
  24. pdflinkcheck/data/themes/forest/forest-dark/border-hover.png +0 -0
  25. pdflinkcheck/data/themes/forest/forest-dark/border-invalid.png +0 -0
  26. pdflinkcheck/data/themes/forest/forest-dark/card.png +0 -0
  27. pdflinkcheck/data/themes/forest/forest-dark/check-accent.png +0 -0
  28. pdflinkcheck/data/themes/forest/forest-dark/check-basic.png +0 -0
  29. pdflinkcheck/data/themes/forest/forest-dark/check-hover.png +0 -0
  30. pdflinkcheck/data/themes/forest/forest-dark/check-tri-accent.png +0 -0
  31. pdflinkcheck/data/themes/forest/forest-dark/check-tri-basic.png +0 -0
  32. pdflinkcheck/data/themes/forest/forest-dark/check-tri-hover.png +0 -0
  33. pdflinkcheck/data/themes/forest/forest-dark/check-unsel-accent.png +0 -0
  34. pdflinkcheck/data/themes/forest/forest-dark/check-unsel-basic.png +0 -0
  35. pdflinkcheck/data/themes/forest/forest-dark/check-unsel-hover.png +0 -0
  36. pdflinkcheck/data/themes/forest/forest-dark/check-unsel-pressed.png +0 -0
  37. pdflinkcheck/data/themes/forest/forest-dark/combo-button-basic.png +0 -0
  38. pdflinkcheck/data/themes/forest/forest-dark/combo-button-focus.png +0 -0
  39. pdflinkcheck/data/themes/forest/forest-dark/combo-button-hover.png +0 -0
  40. pdflinkcheck/data/themes/forest/forest-dark/down.png +0 -0
  41. pdflinkcheck/data/themes/forest/forest-dark/empty.png +0 -0
  42. pdflinkcheck/data/themes/forest/forest-dark/hor-accent.png +0 -0
  43. pdflinkcheck/data/themes/forest/forest-dark/hor-basic.png +0 -0
  44. pdflinkcheck/data/themes/forest/forest-dark/hor-hover.png +0 -0
  45. pdflinkcheck/data/themes/forest/forest-dark/notebook.png +0 -0
  46. pdflinkcheck/data/themes/forest/forest-dark/off-accent.png +0 -0
  47. pdflinkcheck/data/themes/forest/forest-dark/off-basic.png +0 -0
  48. pdflinkcheck/data/themes/forest/forest-dark/off-hover.png +0 -0
  49. pdflinkcheck/data/themes/forest/forest-dark/on-accent.png +0 -0
  50. pdflinkcheck/data/themes/forest/forest-dark/on-basic.png +0 -0
  51. pdflinkcheck/data/themes/forest/forest-dark/on-hover.png +0 -0
  52. pdflinkcheck/data/themes/forest/forest-dark/radio-accent.png +0 -0
  53. pdflinkcheck/data/themes/forest/forest-dark/radio-basic.png +0 -0
  54. pdflinkcheck/data/themes/forest/forest-dark/radio-hover.png +0 -0
  55. pdflinkcheck/data/themes/forest/forest-dark/radio-tri-accent.png +0 -0
  56. pdflinkcheck/data/themes/forest/forest-dark/radio-tri-basic.png +0 -0
  57. pdflinkcheck/data/themes/forest/forest-dark/radio-tri-hover.png +0 -0
  58. pdflinkcheck/data/themes/forest/forest-dark/radio-unsel-accent.png +0 -0
  59. pdflinkcheck/data/themes/forest/forest-dark/radio-unsel-basic.png +0 -0
  60. pdflinkcheck/data/themes/forest/forest-dark/radio-unsel-hover.png +0 -0
  61. pdflinkcheck/data/themes/forest/forest-dark/radio-unsel-pressed.png +0 -0
  62. pdflinkcheck/data/themes/forest/forest-dark/rect-accent-hover.png +0 -0
  63. pdflinkcheck/data/themes/forest/forest-dark/rect-accent.png +0 -0
  64. pdflinkcheck/data/themes/forest/forest-dark/rect-basic.png +0 -0
  65. pdflinkcheck/data/themes/forest/forest-dark/rect-hover.png +0 -0
  66. pdflinkcheck/data/themes/forest/forest-dark/right.png +0 -0
  67. pdflinkcheck/data/themes/forest/forest-dark/scale-hor.png +0 -0
  68. pdflinkcheck/data/themes/forest/forest-dark/scale-vert.png +0 -0
  69. pdflinkcheck/data/themes/forest/forest-dark/separator.png +0 -0
  70. pdflinkcheck/data/themes/forest/forest-dark/sizegrip.png +0 -0
  71. pdflinkcheck/data/themes/forest/forest-dark/spin-button-down-basic.png +0 -0
  72. pdflinkcheck/data/themes/forest/forest-dark/spin-button-down-focus.png +0 -0
  73. pdflinkcheck/data/themes/forest/forest-dark/spin-button-up.png +0 -0
  74. pdflinkcheck/data/themes/forest/forest-dark/tab-accent.png +0 -0
  75. pdflinkcheck/data/themes/forest/forest-dark/tab-basic.png +0 -0
  76. pdflinkcheck/data/themes/forest/forest-dark/tab-hover.png +0 -0
  77. pdflinkcheck/data/themes/forest/forest-dark/thumb-hor-accent.png +0 -0
  78. pdflinkcheck/data/themes/forest/forest-dark/thumb-hor-basic.png +0 -0
  79. pdflinkcheck/data/themes/forest/forest-dark/thumb-hor-hover.png +0 -0
  80. pdflinkcheck/data/themes/forest/forest-dark/thumb-vert-accent.png +0 -0
  81. pdflinkcheck/data/themes/forest/forest-dark/thumb-vert-basic.png +0 -0
  82. pdflinkcheck/data/themes/forest/forest-dark/thumb-vert-hover.png +0 -0
  83. pdflinkcheck/data/themes/forest/forest-dark/tree-basic.png +0 -0
  84. pdflinkcheck/data/themes/forest/forest-dark/tree-pressed.png +0 -0
  85. pdflinkcheck/data/themes/forest/forest-dark/up.png +0 -0
  86. pdflinkcheck/data/themes/forest/forest-dark/vert-accent.png +0 -0
  87. pdflinkcheck/data/themes/forest/forest-dark/vert-basic.png +0 -0
  88. pdflinkcheck/data/themes/forest/forest-dark/vert-hover.png +0 -0
  89. pdflinkcheck/data/themes/forest/forest-dark.tcl +536 -0
  90. pdflinkcheck/data/themes/forest/forest-light/border-accent-hover.png +0 -0
  91. pdflinkcheck/data/themes/forest/forest-light/border-accent.png +0 -0
  92. pdflinkcheck/data/themes/forest/forest-light/border-basic.png +0 -0
  93. pdflinkcheck/data/themes/forest/forest-light/border-hover.png +0 -0
  94. pdflinkcheck/data/themes/forest/forest-light/border-invalid.png +0 -0
  95. pdflinkcheck/data/themes/forest/forest-light/card.png +0 -0
  96. pdflinkcheck/data/themes/forest/forest-light/check-accent.png +0 -0
  97. pdflinkcheck/data/themes/forest/forest-light/check-basic.png +0 -0
  98. pdflinkcheck/data/themes/forest/forest-light/check-hover.png +0 -0
  99. pdflinkcheck/data/themes/forest/forest-light/check-tri-accent.png +0 -0
  100. pdflinkcheck/data/themes/forest/forest-light/check-tri-basic.png +0 -0
  101. pdflinkcheck/data/themes/forest/forest-light/check-tri-hover.png +0 -0
  102. pdflinkcheck/data/themes/forest/forest-light/check-unsel-accent.png +0 -0
  103. pdflinkcheck/data/themes/forest/forest-light/check-unsel-basic.png +0 -0
  104. pdflinkcheck/data/themes/forest/forest-light/check-unsel-hover.png +0 -0
  105. pdflinkcheck/data/themes/forest/forest-light/check-unsel-pressed.png +0 -0
  106. pdflinkcheck/data/themes/forest/forest-light/combo-button-basic.png +0 -0
  107. pdflinkcheck/data/themes/forest/forest-light/combo-button-focus.png +0 -0
  108. pdflinkcheck/data/themes/forest/forest-light/combo-button-hover.png +0 -0
  109. pdflinkcheck/data/themes/forest/forest-light/down-focus.png +0 -0
  110. pdflinkcheck/data/themes/forest/forest-light/down.png +0 -0
  111. pdflinkcheck/data/themes/forest/forest-light/empty.png +0 -0
  112. pdflinkcheck/data/themes/forest/forest-light/hor-accent.png +0 -0
  113. pdflinkcheck/data/themes/forest/forest-light/hor-basic.png +0 -0
  114. pdflinkcheck/data/themes/forest/forest-light/hor-hover.png +0 -0
  115. pdflinkcheck/data/themes/forest/forest-light/notebook.png +0 -0
  116. pdflinkcheck/data/themes/forest/forest-light/off-accent.png +0 -0
  117. pdflinkcheck/data/themes/forest/forest-light/off-basic.png +0 -0
  118. pdflinkcheck/data/themes/forest/forest-light/off-hover.png +0 -0
  119. pdflinkcheck/data/themes/forest/forest-light/on-accent.png +0 -0
  120. pdflinkcheck/data/themes/forest/forest-light/on-basic.png +0 -0
  121. pdflinkcheck/data/themes/forest/forest-light/on-hover.png +0 -0
  122. pdflinkcheck/data/themes/forest/forest-light/radio-accent.png +0 -0
  123. pdflinkcheck/data/themes/forest/forest-light/radio-basic.png +0 -0
  124. pdflinkcheck/data/themes/forest/forest-light/radio-hover.png +0 -0
  125. pdflinkcheck/data/themes/forest/forest-light/radio-tri-accent.png +0 -0
  126. pdflinkcheck/data/themes/forest/forest-light/radio-tri-basic.png +0 -0
  127. pdflinkcheck/data/themes/forest/forest-light/radio-tri-hover.png +0 -0
  128. pdflinkcheck/data/themes/forest/forest-light/radio-unsel-accent.png +0 -0
  129. pdflinkcheck/data/themes/forest/forest-light/radio-unsel-basic.png +0 -0
  130. pdflinkcheck/data/themes/forest/forest-light/radio-unsel-hover.png +0 -0
  131. pdflinkcheck/data/themes/forest/forest-light/radio-unsel-pressed.png +0 -0
  132. pdflinkcheck/data/themes/forest/forest-light/rect-accent-hover.png +0 -0
  133. pdflinkcheck/data/themes/forest/forest-light/rect-accent.png +0 -0
  134. pdflinkcheck/data/themes/forest/forest-light/rect-basic.png +0 -0
  135. pdflinkcheck/data/themes/forest/forest-light/rect-hover.png +0 -0
  136. pdflinkcheck/data/themes/forest/forest-light/right-focus.png +0 -0
  137. pdflinkcheck/data/themes/forest/forest-light/right.png +0 -0
  138. pdflinkcheck/data/themes/forest/forest-light/scale-hor.png +0 -0
  139. pdflinkcheck/data/themes/forest/forest-light/scale-vert.png +0 -0
  140. pdflinkcheck/data/themes/forest/forest-light/separator.png +0 -0
  141. pdflinkcheck/data/themes/forest/forest-light/sizegrip.png +0 -0
  142. pdflinkcheck/data/themes/forest/forest-light/spin-button-down-basic.png +0 -0
  143. pdflinkcheck/data/themes/forest/forest-light/spin-button-down-focus.png +0 -0
  144. pdflinkcheck/data/themes/forest/forest-light/spin-button-up.png +0 -0
  145. pdflinkcheck/data/themes/forest/forest-light/tab-accent.png +0 -0
  146. pdflinkcheck/data/themes/forest/forest-light/tab-basic.png +0 -0
  147. pdflinkcheck/data/themes/forest/forest-light/tab-hover.png +0 -0
  148. pdflinkcheck/data/themes/forest/forest-light/thumb-hor-accent.png +0 -0
  149. pdflinkcheck/data/themes/forest/forest-light/thumb-hor-basic.png +0 -0
  150. pdflinkcheck/data/themes/forest/forest-light/thumb-hor-hover.png +0 -0
  151. pdflinkcheck/data/themes/forest/forest-light/thumb-vert-accent.png +0 -0
  152. pdflinkcheck/data/themes/forest/forest-light/thumb-vert-basic.png +0 -0
  153. pdflinkcheck/data/themes/forest/forest-light/thumb-vert-hover.png +0 -0
  154. pdflinkcheck/data/themes/forest/forest-light/tree-basic.png +0 -0
  155. pdflinkcheck/data/themes/forest/forest-light/tree-pressed.png +0 -0
  156. pdflinkcheck/data/themes/forest/forest-light/up.png +0 -0
  157. pdflinkcheck/data/themes/forest/forest-light/vert-accent.png +0 -0
  158. pdflinkcheck/data/themes/forest/forest-light/vert-basic.png +0 -0
  159. pdflinkcheck/data/themes/forest/forest-light/vert-hover.png +0 -0
  160. pdflinkcheck/data/themes/forest/forest-light.tcl +544 -0
  161. pdflinkcheck/datacopy.py +18 -1
  162. pdflinkcheck/dev.py +12 -25
  163. pdflinkcheck/environment.py +76 -0
  164. pdflinkcheck/gui.py +366 -457
  165. pdflinkcheck/helpers.py +88 -0
  166. pdflinkcheck/io.py +27 -23
  167. pdflinkcheck/report.py +692 -121
  168. pdflinkcheck/security.py +189 -0
  169. pdflinkcheck/splash.py +38 -0
  170. pdflinkcheck/stdlib_server.py +14 -20
  171. pdflinkcheck/stdlib_server_alt.py +571 -0
  172. pdflinkcheck/tk_utils.py +188 -0
  173. pdflinkcheck/update_msix_version.py +49 -0
  174. pdflinkcheck/validate.py +129 -218
  175. pdflinkcheck/version_info.py +6 -3
  176. {pdflinkcheck-1.1.73.dist-info → pdflinkcheck-1.2.29.dist-info}/METADATA +84 -81
  177. pdflinkcheck-1.2.29.dist-info/RECORD +183 -0
  178. pdflinkcheck-1.2.29.dist-info/WHEEL +5 -0
  179. {pdflinkcheck-1.1.73.dist-info → pdflinkcheck-1.2.29.dist-info}/entry_points.txt +0 -1
  180. pdflinkcheck-1.2.29.dist-info/licenses/LICENSE +27 -0
  181. pdflinkcheck-1.2.29.dist-info/licenses/LICENSE-MIT +9 -0
  182. pdflinkcheck-1.2.29.dist-info/top_level.txt +1 -0
  183. pdflinkcheck/analyze_pypdf_v2.py +0 -218
  184. pdflinkcheck-1.1.73.dist-info/RECORD +0 -21
  185. pdflinkcheck-1.1.73.dist-info/WHEEL +0 -4
  186. /pdflinkcheck-1.1.73.dist-info/licenses/LICENSE → /pdflinkcheck-1.2.29.dist-info/licenses/LICENSE-AGPL3 +0 -0
@@ -0,0 +1,88 @@
1
+ # src/pdflinkcheck/helpers.py
2
+ from __future__ import annotations
3
+ from pprint import pprint
4
+ from typing import Any
5
+
6
+ """
7
+ Helper functions
8
+ """
9
+
10
+ def debug_head(label: str, data: Any, n: int = 3):
11
+ """Helper to cleanly print the first N items of a list or dict."""
12
+ print(f"\n--- [DEBUG: {label}] ---")
13
+ if isinstance(data, list):
14
+ pprint(data[:n], indent=2, compact=True, width=100)
15
+ elif isinstance(data, dict):
16
+ # Print first N keys
17
+ head_dict = {k: data[k] for k in list(data.keys())[:n]}
18
+ pprint(head_dict, indent=2, compact=True, width=100)
19
+ else:
20
+ print(data)
21
+
22
+
23
+ class PageRef:
24
+ """
25
+ A simple translator to handle the 0-to-1 index conversion
26
+ without the 'Double Bump' risk.
27
+ """
28
+ def __init__(self, index: int):
29
+ self.index = index # The 0-based physical index
30
+
31
+ @property
32
+ def human(self) -> int:
33
+ """The 1-based page number for humans."""
34
+ return self.index + 1
35
+
36
+ @property
37
+ def machine(self) -> int:
38
+ """Alias for index. The 0-based page number for machines."""
39
+ return self.index
40
+
41
+
42
+ @classmethod
43
+ def corrected_down(cls, human_num: int) -> "PageRef":
44
+ """Explicitly compensates for 1-based data (e.g., PyMuPDF TOC)."""
45
+ return cls.from_human(human_num)
46
+
47
+ @classmethod
48
+ def from_pymupdf_total_page_count(cls, total_pages: int) -> "PageRef":
49
+ """
50
+ Converts PyMuPDF's doc.page_count into a PageRef
51
+ representing the final valid machine-facing index.
52
+ """
53
+ return cls.from_human(total_pages)
54
+
55
+ @classmethod
56
+ def from_human(cls, human_num: int) -> "PageRef":
57
+ """Creates a PageRef from a 1-based human page number (e.g., from TOC)."""
58
+ return cls(human_num - 1)
59
+
60
+ @classmethod
61
+ def from_index(cls, physical_index: int) -> "PageRef":
62
+ """Creates a PageRef from a 0-based physical index (e.g., from links)."""
63
+ return cls(physical_index)
64
+
65
+ def __int__(self):
66
+ return self.index
67
+
68
+ def __str__(self):
69
+ return str(self.human)
70
+
71
+ def __repr__(self):
72
+ return f"PageRef(index={self.index}, human={self.human})"
73
+
74
+
75
+ """
76
+ ### Indexing Map: Physical (0) vs. Logical (1)
77
+
78
+ | **File** | **Context** | **Index Rule** | **Reasoning** |
79
+ | --------------------- | ---------------- | ------------------- | ------------------------------------------------------------------------------------------------------ |
80
+ | `ffi.py` (Rust bridge)| Data Extraction | **0-indexing only** | Rust's `pdf-extract` and `lopdf` crates are 0-indexed. Data should stay raw. |
81
+ | `analysis_pypdf.py` | Data Extraction | **0-indexing only** | `pypdf` is 0-indexed. Your previous `+ 1` hacks have been removed. |
82
+ | `analysis_pymupdf.py` | Data Extraction | **Mixed** | **Internal:** 0-indexed. **TOC:** `get_toc()` is natively 1-indexed. Needs normalization. |
83
+ | `validate.py` | Logic/Validation | **Mixed** | **Logic:** Uses `START_INDEX=0` for boundary checks. **Strings:** Formats error messages as 1-indexed. |
84
+ | `report.py` | Output/Reporting | **Mixed** | **Data:** Keeps dictionary values at 0. **Display:** Formats CLI tables as 1-indexed. |
85
+ | `helpers.py` | Translation | **Mixed** | The `PageRef` class acts as the "Border Control" between 0 and 1. |
86
+ | `__init__.py` | API Surface | **0-indexing only** | If exposing a library, users expect 0-indexed lists of pages/links. |
87
+
88
+ """
pdflinkcheck/io.py CHANGED
@@ -1,9 +1,14 @@
1
+ #!/usr/bin/env python3
2
+ # SPDX-License-Identifier: MIT
1
3
  # src/pdflinkcheck/io.py
4
+ from __future__ import annotations
2
5
  import logging
3
6
  import json
4
7
  import sys
5
8
  from pathlib import Path
6
9
  from typing import Dict, Any, Union, List, Optional
10
+ from datetime import datetime
11
+ import time
7
12
 
8
13
  # --- Configuration ---
9
14
 
@@ -112,13 +117,15 @@ def export_report_json(
112
117
  pdf_library: str
113
118
  ) -> Path:
114
119
  """Exports structured dictionary results to a .json file."""
120
+
115
121
  base_name = Path(pdf_filename).stem
116
- output_path = PDFLINKCHECK_HOME / f"{base_name}_{pdf_library}_report.json"
122
+ output_path = PDFLINKCHECK_HOME / f"{base_name}_{pdf_library}_{get_unique_unix_time()}_report.json"
117
123
 
124
+ print("For more details, explore the exported file(s).")
118
125
  try:
119
126
  with open(output_path, 'w', encoding='utf-8') as f:
120
127
  json.dump(report_data, f, indent=4)
121
- print(f"\nJSON report exported: {get_friendly_path(output_path)}")
128
+ print(f"JSON report exported: {get_friendly_path(output_path)}")
122
129
  return output_path
123
130
  except Exception as e:
124
131
  error_logger.error(f"JSON export failed: {e}", exc_info=True)
@@ -130,35 +137,18 @@ def export_report_txt(
130
137
  pdf_library: str
131
138
  ) -> Path:
132
139
  """Exports the formatted string buffer to a .txt file."""
140
+ #pdf_filename = implement_non_redundant_naming(pdf_filename)
133
141
  base_name = Path(pdf_filename).stem
134
- output_path = PDFLINKCHECK_HOME / f"{base_name}_{pdf_library}_report.txt"
142
+ output_path = PDFLINKCHECK_HOME / f"{base_name}_{pdf_library}_{get_unique_unix_time()}_report.txt"
135
143
 
136
144
  try:
137
145
  output_path.write_text(report_text, encoding='utf-8')
138
- print(f"\nTXT report exported: {get_friendly_path(output_path)}")
146
+ print(f"TXT report exported: {get_friendly_path(output_path)}")
139
147
  return output_path
140
148
  except Exception as e:
141
149
  error_logger.error(f"TXT export failed: {e}", exc_info=True)
142
150
  raise RuntimeError(f"TXT export failed: {e}")
143
151
 
144
- def export_validation_json(
145
- report_data: Dict[str, Any],
146
- pdf_filename: str,
147
- pdf_library: str
148
- ) -> Path:
149
- """Exports structured dictionary validation results to a .json file."""
150
- base_name = Path(pdf_filename).stem
151
- output_path = PDFLINKCHECK_HOME / f"{base_name}_{pdf_library}_validation.json"
152
-
153
- try:
154
- with open(output_path, 'w', encoding='utf-8') as f:
155
- json.dump(report_data, f, indent=4)
156
- print(f"\nJSON validation exported: {get_friendly_path(output_path)}")
157
- return output_path
158
- except Exception as e:
159
- error_logger.error(f"JSON validation export failed: {e}", exc_info=True)
160
- raise RuntimeError(f"JSON validation export failed: {e}")
161
-
162
152
  # --- helpers ---
163
153
  def get_friendly_path(full_path: str) -> str:
164
154
  p = Path(full_path).resolve()
@@ -168,6 +158,20 @@ def get_friendly_path(full_path: str) -> str:
168
158
  except ValueError:
169
159
  return str(p)
170
160
 
161
+ def get_unique_unix_time():
162
+ """
163
+ Get the unix time for right now.
164
+ Purpose: When added to a filename, this ensures a unique filename, to avoid overwrites for otherwise identical filenames.
165
+ Pros:
166
+ - cheap, easy, no reason to check for collision
167
+
168
+ Cons:
169
+ - Longer than YYYYMMDDalpha
170
+ - not human readable
171
+ """
172
+ return int(time.mktime(datetime.now().timetuple()))
173
+
174
+
171
175
  def get_first_pdf_in_cwd() -> Optional[str]:
172
176
  """
173
177
  Scans the current working directory (CWD) for the first file ending
@@ -210,4 +214,4 @@ def get_first_pdf_in_cwd() -> Optional[str]:
210
214
  except Exception as e:
211
215
  # Handle potential permissions errors or other issues
212
216
  print(f"Error while searching for PDF in CWD: {e}", file=sys.stderr)
213
- return None
217
+ return None