zebra-day 0.0.37__py3-none-any.whl → 2.0.0__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 (173) hide show
  1. zebra_day/__init__.py +35 -0
  2. zebra_day/bin/__init__.py +0 -0
  3. zebra_day/cli/__init__.py +240 -0
  4. zebra_day/cli/cognito.py +121 -0
  5. zebra_day/cli/gui.py +338 -0
  6. zebra_day/cli/printer.py +168 -0
  7. zebra_day/cli/template.py +176 -0
  8. zebra_day/cmd_mgr.py +35 -0
  9. zebra_day/etc/Monoid-Regular-HalfTight-Dollar-0-1-l.ttf +0 -0
  10. zebra_day/etc/label_styles/blank.zpl +0 -0
  11. zebra_day/etc/label_styles/cornersStripOf4Squares_1inX1in.zpl +55 -0
  12. zebra_day/etc/label_styles/corners_1inX2in.zpl +28 -0
  13. zebra_day/etc/label_styles/corners_20cmX30cm.zpl +6 -0
  14. zebra_day/etc/label_styles/corners_smallTube.zpl +7 -0
  15. zebra_day/etc/label_styles/corners_unspecifiedDimensions.zpl +15 -0
  16. zebra_day/etc/label_styles/generic_2inX1in.zpl +21 -0
  17. zebra_day/etc/label_styles/plate_1inX0.25in.zpl +9 -0
  18. zebra_day/etc/label_styles/plate_1inX0.25inHD.zpl +9 -0
  19. zebra_day/etc/label_styles/smallTubeWdotHD_prod.zpl +8 -0
  20. zebra_day/etc/label_styles/smallTubeWdot_corners.zpl +7 -0
  21. zebra_day/etc/label_styles/smallTubeWdot_prod.zpl +8 -0
  22. zebra_day/etc/label_styles/smallTubeWdot_prodAlt1.zpl +6 -0
  23. zebra_day/etc/label_styles/smallTubeWdot_prodAlt1b.zpl +3 -0
  24. zebra_day/etc/label_styles/smallTubeWdot_prodV2.zpl +8 -0
  25. zebra_day/etc/label_styles/smallTubeWdot_reagent.zpl +29 -0
  26. zebra_day/etc/label_styles/stripOf4Squares_1inX1in.zpl +32 -0
  27. zebra_day/etc/label_styles/test_800dX800dCoordinateArray.zpl +1 -0
  28. zebra_day/etc/label_styles/tmps/.hold +0 -0
  29. zebra_day/etc/label_styles/tmps/tmp_zpl_templates.here +0 -0
  30. zebra_day/etc/label_styles/tube_20mmX30mmA.zpl +7 -0
  31. zebra_day/etc/label_styles/tube_2inX0.3in.zpl +15 -0
  32. zebra_day/etc/label_styles/tube_2inX0.5in.zpl +15 -0
  33. zebra_day/etc/label_styles/tube_2inX0.5inHD.zpl +15 -0
  34. zebra_day/etc/label_styles/tube_2inX1in.zpl +25 -0
  35. zebra_day/etc/label_styles/tube_2inX1inHD.zpl +22 -0
  36. zebra_day/etc/label_styles/tube_2inX1inHDv3.zpl +21 -0
  37. zebra_day/etc/old_printer_config/.hold +0 -0
  38. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.022846_printer_config.json +1 -0
  39. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.033657_printer_config.json +1 -0
  40. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.039597_printer_config.json +3 -0
  41. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.047295_printer_config.json +1 -0
  42. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.055804_printer_config.json +1 -0
  43. zebra_day/etc/old_printer_config/2026-02-01_01:50:25.061337_printer_config.json +3 -0
  44. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.073326_printer_config.json +1 -0
  45. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.081950_printer_config.json +1 -0
  46. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.088251_printer_config.json +3 -0
  47. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.096501_printer_config.json +1 -0
  48. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.104767_printer_config.json +1 -0
  49. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.110364_printer_config.json +3 -0
  50. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.118239_printer_config.json +1 -0
  51. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.125950_printer_config.json +1 -0
  52. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.349866_printer_config.json +1 -0
  53. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.361085_printer_config.json +3 -0
  54. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.558323_printer_config.json +1 -0
  55. zebra_day/etc/old_printer_config/2026-02-01_01:51:24.565756_printer_config.json +3 -0
  56. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.739070_printer_config.json +16 -0
  57. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.753796_printer_config.json +1 -0
  58. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.760201_printer_config.json +3 -0
  59. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.768747_printer_config.json +1 -0
  60. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.775312_printer_config.json +3 -0
  61. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.782533_printer_config.json +1 -0
  62. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.789287_printer_config.json +1 -0
  63. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.794230_printer_config.json +3 -0
  64. zebra_day/etc/old_printer_config/2026-02-01_01:51:29.800021_printer_config.json +5 -0
  65. zebra_day/etc/printer_config.json +4 -0
  66. zebra_day/etc/printer_config.template.json +24 -0
  67. zebra_day/etc/tmp_printers0.json +5 -0
  68. zebra_day/etc/tmp_printers120.json +10 -0
  69. zebra_day/etc/tmp_printers145.json +10 -0
  70. zebra_day/etc/tmp_printers207.json +10 -0
  71. zebra_day/etc/tmp_printers374.json +5 -0
  72. zebra_day/etc/tmp_printers383.json +5 -0
  73. zebra_day/etc/tmp_printers450.json +5 -0
  74. zebra_day/etc/tmp_printers469.json +10 -0
  75. zebra_day/etc/tmp_printers485.json +10 -0
  76. zebra_day/etc/tmp_printers504.json +5 -0
  77. zebra_day/etc/tmp_printers531.json +10 -0
  78. zebra_day/etc/tmp_printers540.json +10 -0
  79. zebra_day/etc/tmp_printers542.json +10 -0
  80. zebra_day/etc/tmp_printers552.json +10 -0
  81. zebra_day/etc/tmp_printers608.json +5 -0
  82. zebra_day/etc/tmp_printers657.json +5 -0
  83. zebra_day/etc/tmp_printers715.json +10 -0
  84. zebra_day/etc/tmp_printers838.json +5 -0
  85. zebra_day/etc/tmp_printers839.json +5 -0
  86. zebra_day/etc/tmp_printers933.json +5 -0
  87. zebra_day/etc/tmp_printers957.json +5 -0
  88. zebra_day/etc/tmp_printers972.json +10 -0
  89. zebra_day/exceptions.py +88 -0
  90. zebra_day/files/.hold +0 -0
  91. zebra_day/files/blank_preview.png +0 -0
  92. zebra_day/files/corners_20cmX30cm_preview.png +0 -0
  93. zebra_day/files/generic_2inX1in_preview.png +0 -0
  94. zebra_day/files/hold +0 -0
  95. zebra_day/files/test_png_12020.png +0 -0
  96. zebra_day/files/test_png_12352.png +0 -0
  97. zebra_day/files/test_png_15472.png +0 -0
  98. zebra_day/files/test_png_17696.png +0 -0
  99. zebra_day/files/test_png_23477.png +0 -0
  100. zebra_day/files/test_png_24493.png +0 -0
  101. zebra_day/files/test_png_28157.png +0 -0
  102. zebra_day/files/test_png_30069.png +0 -0
  103. zebra_day/files/test_png_35832.png +0 -0
  104. zebra_day/files/test_png_36400.png +0 -0
  105. zebra_day/files/test_png_40816.png +0 -0
  106. zebra_day/files/test_png_47791.png +0 -0
  107. zebra_day/files/test_png_47799.png +0 -0
  108. zebra_day/files/test_png_49564.png +0 -0
  109. zebra_day/files/test_png_53848.png +0 -0
  110. zebra_day/files/test_png_55588.png +0 -0
  111. zebra_day/files/test_png_58809.png +0 -0
  112. zebra_day/files/test_png_62542.png +0 -0
  113. zebra_day/files/test_png_67242.png +0 -0
  114. zebra_day/files/test_png_89893.png +0 -0
  115. zebra_day/files/test_png_91597.png +0 -0
  116. zebra_day/files/test_png_93633.png +0 -0
  117. zebra_day/files/tmpbjo3k7q1.png +0 -0
  118. zebra_day/files/tmpigtr4pwy.png +0 -0
  119. zebra_day/files/tube_20mmX30mmA_preview.png +0 -0
  120. zebra_day/files/zpl_label_tube_2inX1in_2026-02-01_01:51:24.370964.png +0 -0
  121. zebra_day/logging_config.py +74 -0
  122. zebra_day/logs/.hold +0 -0
  123. zebra_day/logs/print_requests.log +2 -0
  124. zebra_day/paths.py +143 -0
  125. zebra_day/print_mgr.py +557 -117
  126. zebra_day/static/datschund.css +140 -0
  127. zebra_day/static/datschund.png +0 -0
  128. zebra_day/static/daylily.png +0 -0
  129. zebra_day/static/favicon.svg +20 -0
  130. zebra_day/static/general.css +99 -0
  131. zebra_day/static/js/zebra_modern.js +172 -0
  132. zebra_day/static/lsmc.css +354 -0
  133. zebra_day/static/moon.jpeg +0 -0
  134. zebra_day/static/oakland.css +197 -0
  135. zebra_day/static/petrichor.css +150 -0
  136. zebra_day/static/popday_daylily.css +140 -0
  137. zebra_day/static/style.css +183 -0
  138. zebra_day/static/triangles.css +122 -0
  139. zebra_day/static/tron.css +277 -0
  140. zebra_day/static/zebra_modern.css +771 -0
  141. zebra_day/static/zebras.css +176 -0
  142. zebra_day/templates/modern/base.html +98 -0
  143. zebra_day/templates/modern/config.html +141 -0
  144. zebra_day/templates/modern/config_backups.html +59 -0
  145. zebra_day/templates/modern/config_editor.html +95 -0
  146. zebra_day/templates/modern/config_new.html +93 -0
  147. zebra_day/templates/modern/dashboard.html +160 -0
  148. zebra_day/templates/modern/print_request.html +145 -0
  149. zebra_day/templates/modern/print_result.html +88 -0
  150. zebra_day/templates/modern/printer_detail.html +244 -0
  151. zebra_day/templates/modern/printers.html +144 -0
  152. zebra_day/templates/modern/save_result.html +46 -0
  153. zebra_day/templates/modern/template_editor.html +175 -0
  154. zebra_day/templates/modern/templates.html +122 -0
  155. zebra_day/web/__init__.py +9 -0
  156. zebra_day/web/app.py +248 -0
  157. zebra_day/web/auth.py +172 -0
  158. zebra_day/web/middleware.py +159 -0
  159. zebra_day/web/routers/__init__.py +2 -0
  160. zebra_day/web/routers/api.py +313 -0
  161. zebra_day/web/routers/ui.py +636 -0
  162. zebra_day/zpl_renderer.py +273 -0
  163. zebra_day-2.0.0.dist-info/METADATA +847 -0
  164. zebra_day-2.0.0.dist-info/RECORD +168 -0
  165. {zebra_day-0.0.37.dist-info → zebra_day-2.0.0.dist-info}/WHEEL +1 -1
  166. zebra_day-2.0.0.dist-info/entry_points.txt +4 -0
  167. zebra_day/bin/scan_for_networed_zebra_printers.py +0 -23
  168. zebra_day/bin/te.py +0 -905
  169. zebra_day/bin/zserve.py +0 -620
  170. zebra_day-0.0.37.dist-info/METADATA +0 -1177
  171. zebra_day-0.0.37.dist-info/RECORD +0 -10
  172. {zebra_day-0.0.37.dist-info → zebra_day-2.0.0.dist-info/licenses}/LICENSE +0 -0
  173. {zebra_day-0.0.37.dist-info → zebra_day-2.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,10 @@
1
+ {
2
+ "schema_version": "2.0.0",
3
+ "labs": {
4
+ "test": {
5
+ "lab_name": "Test Lab",
6
+ "available_locations": [],
7
+ "printers": {}
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "schema_version": "2.0.0",
3
+ "labs": {
4
+ "test": {
5
+ "lab_name": "Test Lab",
6
+ "available_locations": [],
7
+ "printers": {}
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "schema_version": "2.0.0",
3
+ "labs": {
4
+ "test": {
5
+ "lab_name": "Test Lab",
6
+ "available_locations": [],
7
+ "printers": {}
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "labs": {
3
+ "test": {}
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "labs": {
3
+ "test": {}
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "labs": {
3
+ "test": {}
4
+ }
5
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "schema_version": "2.0.0",
3
+ "labs": {
4
+ "test": {
5
+ "lab_name": "Test Lab",
6
+ "available_locations": [],
7
+ "printers": {}
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "schema_version": "2.0.0",
3
+ "labs": {
4
+ "test": {
5
+ "lab_name": "Test Lab",
6
+ "available_locations": [],
7
+ "printers": {}
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "labs": {
3
+ "test": {}
4
+ }
5
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "schema_version": "2.0.0",
3
+ "labs": {
4
+ "test": {
5
+ "lab_name": "Test Lab",
6
+ "available_locations": [],
7
+ "printers": {}
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "schema_version": "2.0.0",
3
+ "labs": {
4
+ "test": {
5
+ "lab_name": "Test Lab",
6
+ "available_locations": [],
7
+ "printers": {}
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "schema_version": "2.0.0",
3
+ "labs": {
4
+ "test": {
5
+ "lab_name": "Test Lab",
6
+ "available_locations": [],
7
+ "printers": {}
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "schema_version": "2.0.0",
3
+ "labs": {
4
+ "test": {
5
+ "lab_name": "Test Lab",
6
+ "available_locations": [],
7
+ "printers": {}
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "labs": {
3
+ "test": {}
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "labs": {
3
+ "test": {}
4
+ }
5
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "schema_version": "2.0.0",
3
+ "labs": {
4
+ "test": {
5
+ "lab_name": "Test Lab",
6
+ "available_locations": [],
7
+ "printers": {}
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "labs": {
3
+ "test": {}
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "labs": {
3
+ "test": {}
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "labs": {
3
+ "test": {}
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "labs": {
3
+ "test": {}
4
+ }
5
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "schema_version": "2.0.0",
3
+ "labs": {
4
+ "test": {
5
+ "lab_name": "Test Lab",
6
+ "available_locations": [],
7
+ "printers": {}
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,88 @@
1
+ """
2
+ Custom exceptions for zebra_day.
3
+
4
+ Provides specific exception types for different error conditions.
5
+ """
6
+ from __future__ import annotations
7
+
8
+
9
+ class ZebraDayError(Exception):
10
+ """Base exception for all zebra_day errors."""
11
+
12
+ pass
13
+
14
+
15
+ class PrinterConnectionError(ZebraDayError):
16
+ """Raised when unable to connect to a printer."""
17
+
18
+ def __init__(self, printer_ip: str, message: str = ""):
19
+ self.printer_ip = printer_ip
20
+ super().__init__(f"Failed to connect to printer at {printer_ip}: {message}")
21
+
22
+
23
+ class PrinterNotFoundError(ZebraDayError):
24
+ """Raised when a printer is not found in the configuration."""
25
+
26
+ def __init__(self, printer_name: str, lab: str = ""):
27
+ self.printer_name = printer_name
28
+ self.lab = lab
29
+ msg = f"Printer '{printer_name}' not found"
30
+ if lab:
31
+ msg += f" in lab '{lab}'"
32
+ super().__init__(msg)
33
+
34
+
35
+ class ConfigError(ZebraDayError):
36
+ """Raised when there's an issue with configuration."""
37
+
38
+ def __init__(self, message: str, config_path: str = ""):
39
+ self.config_path = config_path
40
+ super().__init__(message)
41
+
42
+
43
+ class ConfigFileNotFoundError(ConfigError):
44
+ """Raised when a configuration file is not found."""
45
+
46
+ def __init__(self, path: str):
47
+ super().__init__(f"Configuration file not found: {path}", config_path=path)
48
+
49
+
50
+ class ConfigParseError(ConfigError):
51
+ """Raised when a configuration file cannot be parsed."""
52
+
53
+ def __init__(self, path: str, details: str = ""):
54
+ msg = f"Failed to parse configuration file: {path}"
55
+ if details:
56
+ msg += f" ({details})"
57
+ super().__init__(msg, config_path=path)
58
+
59
+
60
+ class LabelTemplateError(ZebraDayError):
61
+ """Raised when there's an issue with a label template."""
62
+
63
+ def __init__(self, template_name: str, message: str = ""):
64
+ self.template_name = template_name
65
+ super().__init__(f"Label template error '{template_name}': {message}")
66
+
67
+
68
+ class LabelTemplateNotFoundError(LabelTemplateError):
69
+ """Raised when a label template file is not found."""
70
+
71
+ def __init__(self, template_name: str):
72
+ super().__init__(template_name, "template not found")
73
+
74
+
75
+ class ZPLRenderError(ZebraDayError):
76
+ """Raised when ZPL rendering fails."""
77
+
78
+ def __init__(self, message: str):
79
+ super().__init__(f"ZPL render error: {message}")
80
+
81
+
82
+ class NetworkScanError(ZebraDayError):
83
+ """Raised when network scanning for printers fails."""
84
+
85
+ def __init__(self, ip_stub: str, message: str = ""):
86
+ self.ip_stub = ip_stub
87
+ super().__init__(f"Network scan failed for {ip_stub}.*: {message}")
88
+
zebra_day/files/.hold ADDED
File without changes
Binary file
zebra_day/files/hold ADDED
File without changes
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,74 @@
1
+ """
2
+ Logging configuration for zebra_day.
3
+
4
+ Provides structured logging with configurable levels and formats.
5
+ """
6
+ from __future__ import annotations
7
+
8
+ import logging
9
+ import sys
10
+ from pathlib import Path
11
+ from typing import Optional
12
+
13
+
14
+ def get_logger(name: str) -> logging.Logger:
15
+ """Get a logger with the zebra_day namespace.
16
+
17
+ Args:
18
+ name: Module name (typically __name__)
19
+
20
+ Returns:
21
+ Configured logger instance
22
+ """
23
+ if name.startswith("zebra_day"):
24
+ return logging.getLogger(name)
25
+ return logging.getLogger(f"zebra_day.{name}")
26
+
27
+
28
+ def configure_logging(
29
+ level: int = logging.INFO,
30
+ log_file: Optional[Path] = None,
31
+ format_string: Optional[str] = None,
32
+ ) -> None:
33
+ """Configure zebra_day logging.
34
+
35
+ Args:
36
+ level: Logging level (default: INFO)
37
+ log_file: Optional path to log file
38
+ format_string: Optional custom format string
39
+ """
40
+ if format_string is None:
41
+ format_string = (
42
+ "\033[1m%(asctime)s\033[0m "
43
+ "[%(levelname)s] "
44
+ "%(name)s: %(message)s"
45
+ )
46
+
47
+ formatter = logging.Formatter(format_string, datefmt="%Y-%m-%d %H:%M:%S")
48
+
49
+ # Root zebra_day logger
50
+ logger = logging.getLogger("zebra_day")
51
+ logger.setLevel(level)
52
+
53
+ # Clear existing handlers to avoid duplicates
54
+ logger.handlers.clear()
55
+
56
+ # Console handler (stderr)
57
+ console_handler = logging.StreamHandler(sys.stderr)
58
+ console_handler.setLevel(level)
59
+ console_handler.setFormatter(formatter)
60
+ logger.addHandler(console_handler)
61
+
62
+ # File handler if specified
63
+ if log_file is not None:
64
+ log_file.parent.mkdir(parents=True, exist_ok=True)
65
+ file_handler = logging.FileHandler(log_file)
66
+ file_handler.setLevel(level)
67
+ file_handler.setFormatter(
68
+ logging.Formatter(
69
+ "%(asctime)s [%(levelname)s] %(name)s: %(message)s",
70
+ datefmt="%Y-%m-%d %H:%M:%S",
71
+ )
72
+ )
73
+ logger.addHandler(file_handler)
74
+
zebra_day/logs/.hold ADDED
File without changes
@@ -0,0 +1,2 @@
1
+ scan-results Download-Label-png TESTBC tube_2inX1in dl_png 1 pkg None
2
+
zebra_day/paths.py ADDED
@@ -0,0 +1,143 @@
1
+ """
2
+ XDG Base Directory specification support for zebra_day.
3
+
4
+ This module provides cross-platform paths for configuration, state, cache, and data
5
+ following the XDG Base Directory specification on Linux/macOS.
6
+
7
+ XDG Base Directory Specification:
8
+ - XDG_CONFIG_HOME: User configuration files (~/.config)
9
+ - XDG_DATA_HOME: User data files (~/.local/share)
10
+ - XDG_STATE_HOME: User state files (~/.local/state) - logs, history
11
+ - XDG_CACHE_HOME: User cache files (~/.cache)
12
+
13
+ On macOS, we use ~/Library/Application Support for data and
14
+ ~/Library/Preferences for config, but support XDG overrides.
15
+ """
16
+ from __future__ import annotations
17
+
18
+ import os
19
+ import sys
20
+ from pathlib import Path
21
+ from typing import Optional
22
+
23
+ APP_NAME = "zebra_day"
24
+
25
+
26
+ def _get_xdg_dir(env_var: str, fallback: Path) -> Path:
27
+ """Get XDG directory, respecting environment variable if set."""
28
+ env_value = os.environ.get(env_var)
29
+ if env_value:
30
+ return Path(env_value)
31
+ return fallback
32
+
33
+
34
+ def get_config_dir() -> Path:
35
+ """Get the configuration directory.
36
+
37
+ Returns:
38
+ Path to zebra_day config directory (created if needed)
39
+ """
40
+ if sys.platform == "darwin":
41
+ # macOS: Use XDG if set, otherwise ~/Library/Preferences
42
+ fallback = Path.home() / "Library" / "Preferences" / APP_NAME
43
+ else:
44
+ # Linux/other: Use XDG
45
+ fallback = Path.home() / ".config" / APP_NAME
46
+
47
+ base = _get_xdg_dir("XDG_CONFIG_HOME", fallback.parent)
48
+ config_dir = base / APP_NAME if "XDG_CONFIG_HOME" in os.environ else fallback
49
+ config_dir.mkdir(parents=True, exist_ok=True)
50
+ return config_dir
51
+
52
+
53
+ def get_data_dir() -> Path:
54
+ """Get the data directory for persistent application data.
55
+
56
+ Returns:
57
+ Path to zebra_day data directory (created if needed)
58
+ """
59
+ if sys.platform == "darwin":
60
+ fallback = Path.home() / "Library" / "Application Support" / APP_NAME
61
+ else:
62
+ fallback = Path.home() / ".local" / "share" / APP_NAME
63
+
64
+ base = _get_xdg_dir("XDG_DATA_HOME", fallback.parent)
65
+ data_dir = base / APP_NAME if "XDG_DATA_HOME" in os.environ else fallback
66
+ data_dir.mkdir(parents=True, exist_ok=True)
67
+ return data_dir
68
+
69
+
70
+ def get_state_dir() -> Path:
71
+ """Get the state directory for logs and runtime state.
72
+
73
+ Returns:
74
+ Path to zebra_day state directory (created if needed)
75
+ """
76
+ if sys.platform == "darwin":
77
+ fallback = Path.home() / "Library" / "Logs" / APP_NAME
78
+ else:
79
+ fallback = Path.home() / ".local" / "state" / APP_NAME
80
+
81
+ base = _get_xdg_dir("XDG_STATE_HOME", fallback.parent)
82
+ state_dir = base / APP_NAME if "XDG_STATE_HOME" in os.environ else fallback
83
+ state_dir.mkdir(parents=True, exist_ok=True)
84
+ return state_dir
85
+
86
+
87
+ def get_cache_dir() -> Path:
88
+ """Get the cache directory for temporary files.
89
+
90
+ Returns:
91
+ Path to zebra_day cache directory (created if needed)
92
+ """
93
+ if sys.platform == "darwin":
94
+ fallback = Path.home() / "Library" / "Caches" / APP_NAME
95
+ else:
96
+ fallback = Path.home() / ".cache" / APP_NAME
97
+
98
+ base = _get_xdg_dir("XDG_CACHE_HOME", fallback.parent)
99
+ cache_dir = base / APP_NAME if "XDG_CACHE_HOME" in os.environ else fallback
100
+ cache_dir.mkdir(parents=True, exist_ok=True)
101
+ return cache_dir
102
+
103
+
104
+ # Specific file/directory paths
105
+ def get_printer_config_path() -> Path:
106
+ """Get path to the printer configuration JSON file."""
107
+ return get_config_dir() / "printer_config.json"
108
+
109
+
110
+ def get_label_styles_dir() -> Path:
111
+ """Get path to the label styles directory."""
112
+ styles_dir = get_data_dir() / "label_styles"
113
+ styles_dir.mkdir(parents=True, exist_ok=True)
114
+ return styles_dir
115
+
116
+
117
+ def get_label_drafts_dir() -> Path:
118
+ """Get path to the label drafts (tmps) directory."""
119
+ drafts_dir = get_label_styles_dir() / "tmps"
120
+ drafts_dir.mkdir(parents=True, exist_ok=True)
121
+ return drafts_dir
122
+
123
+
124
+ def get_config_backups_dir() -> Path:
125
+ """Get path to the config backups directory."""
126
+ backups_dir = get_config_dir() / "backups"
127
+ backups_dir.mkdir(parents=True, exist_ok=True)
128
+ return backups_dir
129
+
130
+
131
+ def get_logs_dir() -> Path:
132
+ """Get path to the logs directory."""
133
+ logs_dir = get_state_dir() / "logs"
134
+ logs_dir.mkdir(parents=True, exist_ok=True)
135
+ return logs_dir
136
+
137
+
138
+ def get_generated_files_dir() -> Path:
139
+ """Get path for generated files like PNGs."""
140
+ files_dir = get_cache_dir() / "generated"
141
+ files_dir.mkdir(parents=True, exist_ok=True)
142
+ return files_dir
143
+