pysfi 0.1.14__tar.gz → 0.1.15__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 (152) hide show
  1. {pysfi-0.1.14 → pysfi-0.1.15}/PKG-INFO +1 -1
  2. {pysfi-0.1.14 → pysfi-0.1.15}/pyproject.toml +181 -179
  3. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/__init__.py +1 -1
  4. pysfi-0.1.15/sfi/alarmclock/tests/__init__.py +1 -0
  5. pysfi-0.1.15/sfi/alarmclock/tests/test_alarmclock_core.py +113 -0
  6. pysfi-0.1.15/sfi/alarmclock/tests/test_alarmclock_gui.py +185 -0
  7. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/bumpversion/__init__.py +1 -1
  8. pysfi-0.1.15/sfi/condasetup/README.md +144 -0
  9. pysfi-0.1.15/sfi/condasetup/tests/__init__.py +1 -0
  10. pysfi-0.1.15/sfi/condasetup/tests/test_condasetup.py +173 -0
  11. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docscan/__init__.py +1 -1
  12. pysfi-0.1.15/sfi/gittool/README.md +272 -0
  13. pysfi-0.1.15/sfi/gittool/tests/__init__.py +1 -0
  14. pysfi-0.1.15/sfi/gittool/tests/test_gittool.py +290 -0
  15. pysfi-0.1.15/sfi/pdfcrypt/README.md +184 -0
  16. pysfi-0.1.15/sfi/pdfcrypt/__init__.py +30 -0
  17. pysfi-0.1.15/sfi/pdfcrypt/pdfcrypt.py +435 -0
  18. pysfi-0.1.15/sfi/pdfcrypt/tests/__init__.py +1 -0
  19. pysfi-0.1.15/sfi/pdfcrypt/tests/test_benchmark.py +162 -0
  20. pysfi-0.1.15/sfi/pdfcrypt/tests/test_pdfcrypt.py +226 -0
  21. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyarchive/pyarchive.py +1 -1
  22. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyarchive/tests/test_pyarchive.py +1 -1
  23. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyembedinstall/pyembedinstall.py +1 -1
  24. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pylibpack/tests/test_pylibpack.py +20 -10
  25. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyloadergen/pyloadergen.py +6 -3
  26. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pypack/pypack.py +5 -1
  27. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyprojectparse/pyprojectparse.py +9 -31
  28. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyprojectparse/tests/test_benchmark.py +4 -4
  29. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyprojectparse/tests/test_projectparse.py +32 -27
  30. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pysourcepack/pysourcepack.py +11 -14
  31. pysfi-0.1.15/sfi/pysourcepack/tests/__init__.py +1 -0
  32. pysfi-0.1.15/sfi/pysourcepack/tests/test_benchmark.py +127 -0
  33. pysfi-0.1.15/sfi/pysourcepack/tests/test_functional.py +137 -0
  34. pysfi-0.1.15/sfi/pysourcepack/tests/test_pysourcepack.py +183 -0
  35. pysfi-0.1.14/sfi/llmquantize/README.md +0 -0
  36. pysfi-0.1.14/sfi/llmserver/README.md +0 -0
  37. {pysfi-0.1.14 → pysfi-0.1.15}/.gitignore +0 -0
  38. {pysfi-0.1.14 → pysfi-0.1.15}/README.md +0 -0
  39. {pysfi-0.1.14 → pysfi-0.1.15}/examples/pack_demo/README.md +0 -0
  40. {pysfi-0.1.14 → pysfi-0.1.15}/examples/workflowengine/README.md +0 -0
  41. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/alarmclock/README.md +0 -0
  42. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/alarmclock/__init__.py +0 -0
  43. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/alarmclock/alarmclock.py +0 -0
  44. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/bumpversion/README.md +0 -0
  45. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/bumpversion/bumpversion.py +0 -0
  46. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/bumpversion/tests/__init__.py +0 -0
  47. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/bumpversion/tests/test_bumpversion.py +0 -0
  48. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/cleanbuild/README.md +0 -0
  49. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/cleanbuild/__init__.py +0 -0
  50. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/cleanbuild/cleanbuild.py +0 -0
  51. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/cli.py +0 -0
  52. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/condasetup/__init__.py +0 -0
  53. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/condasetup/condasetup.py +0 -0
  54. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docdiff/README.md +0 -0
  55. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docdiff/__init__.py +0 -0
  56. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docdiff/docdiff.py +0 -0
  57. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docdiff/tests/__init__.py +0 -0
  58. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docdiff/tests/test_benchmark.py +0 -0
  59. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docdiff/tests/test_docdiff.py +0 -0
  60. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docdiff/tests/test_enhanced.py +0 -0
  61. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docdiff/tests/test_functional.py +0 -0
  62. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docscan/README.md +0 -0
  63. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docscan/docscan.py +0 -0
  64. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docscan/docscan_gui.py +0 -0
  65. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docscan/lang/__init__.py +0 -0
  66. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docscan/lang/eng.py +0 -0
  67. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docscan/lang/zhcn.py +0 -0
  68. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docscan/tests/__init__.py +0 -0
  69. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docscan/tests/test_benchmark.py +0 -0
  70. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docscan/tests/test_docscan.py +0 -0
  71. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/docscan/tests/test_enhanced.py +0 -0
  72. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/filedate/README.md +0 -0
  73. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/filedate/__init__.py +0 -0
  74. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/filedate/filedate.py +0 -0
  75. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/filedate/tests/__init__.py +0 -0
  76. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/filedate/tests/test_filedate.py +0 -0
  77. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/gittool/__init__.py +0 -0
  78. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/gittool/gittool.py +0 -0
  79. {pysfi-0.1.14/sfi/condasetup → pysfi-0.1.15/sfi/img2pdf}/README.md +0 -0
  80. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/img2pdf/__init__.py +0 -0
  81. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/img2pdf/img2pdf.py +0 -0
  82. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/img2pdf/tests/__init__.py +0 -0
  83. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/img2pdf/tests/test_benchmark.py +0 -0
  84. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/img2pdf/tests/test_img2pdf.py +0 -0
  85. {pysfi-0.1.14/sfi/gittool → pysfi-0.1.15/sfi/llmclient}/README.md +0 -0
  86. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/llmclient/__init__.py +0 -0
  87. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/llmclient/llmclient.py +0 -0
  88. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/llmclient/tests/__init__.py +0 -0
  89. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/llmclient/tests/test_benchmark.py +0 -0
  90. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/llmclient/tests/test_llmclient.py +0 -0
  91. {pysfi-0.1.14/sfi/img2pdf → pysfi-0.1.15/sfi/llmquantize}/README.md +0 -0
  92. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/llmquantize/__init__.py +0 -0
  93. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/llmquantize/llmquantize.py +0 -0
  94. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/llmquantize/tests/__init__.py +0 -0
  95. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/llmquantize/tests/test_llmquantize.py +0 -0
  96. {pysfi-0.1.14/sfi/llmclient → pysfi-0.1.15/sfi/llmserver}/README.md +0 -0
  97. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/llmserver/__init__.py +0 -0
  98. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/llmserver/llmserver.py +0 -0
  99. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/makepython/README.md +0 -0
  100. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/makepython/__init__.py +0 -0
  101. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/makepython/makepython.py +0 -0
  102. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/makepython/tests/test_benchmark.py +0 -0
  103. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/makepython/tests/test_makepython.py +0 -0
  104. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pdfsplit/__init__.py +0 -0
  105. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pdfsplit/pdfsplit.py +0 -0
  106. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pdfsplit/tests/__init__.py +0 -0
  107. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pdfsplit/tests/test_pdfsplit.py +0 -0
  108. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyarchive/README.md +0 -0
  109. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyarchive/__init__.py +0 -0
  110. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyarchive/tests/__init__.py +0 -0
  111. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyarchive/tests/test_benchmark.py +0 -0
  112. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyembedinstall/__init__.py +0 -0
  113. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyembedinstall/tests/__init__.py +0 -0
  114. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyembedinstall/tests/test_pyembedinstall.py +0 -0
  115. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pylibpack/README.md +0 -0
  116. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pylibpack/__init__.py +0 -0
  117. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pylibpack/pylibpack.py +0 -0
  118. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pylibpack/tests/__init__.py +0 -0
  119. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pylibpack/tests/test_benchmark.py +0 -0
  120. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyloadergen/__init__.py +0 -0
  121. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyloadergen/tests/__init__.py +0 -0
  122. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyloadergen/tests/test_benchmark.py +0 -0
  123. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyloadergen/tests/test_pyloadergen.py +0 -0
  124. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pypack/README.md +0 -0
  125. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pypack/__init__.py +0 -0
  126. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pypack/tests/__init__.py +0 -0
  127. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pypack/tests/test_benchmark.py +0 -0
  128. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pypack/tests/test_pack.py +0 -0
  129. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyprojectparse/README.md +0 -0
  130. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyprojectparse/__init__.py +0 -0
  131. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pyprojectparse/tests/__init__.py +0 -0
  132. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pysourcepack/README.md +0 -0
  133. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/pysourcepack/__init__.py +0 -0
  134. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/quizbase/README.md +0 -0
  135. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/quizbase/__init__.py +0 -0
  136. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/quizbase/quizbase.py +0 -0
  137. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/quizbase/quizbase_gui.py +0 -0
  138. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/quizbase/tests/__init__.py +0 -0
  139. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/quizbase/tests/test_quizbase.py +0 -0
  140. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/quizbase/tests/test_quizbase_gui.py +0 -0
  141. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/regexvalidate/README.md +0 -0
  142. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/regexvalidate/__init__.py +0 -0
  143. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/regexvalidate/regexvalidate.py +0 -0
  144. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/taskkill/README.md +0 -0
  145. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/taskkill/__init__.py +0 -0
  146. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/taskkill/taskkill.py +0 -0
  147. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/taskkill/tests/__init__.py +0 -0
  148. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/taskkill/tests/test_benchmark.py +0 -0
  149. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/taskkill/tests/test_smoke.py +0 -0
  150. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/taskkill/tests/test_taskkill.py +0 -0
  151. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/which/__init__.py +0 -0
  152. {pysfi-0.1.14 → pysfi-0.1.15}/sfi/which/which.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pysfi
3
- Version: 0.1.14
3
+ Version: 0.1.15
4
4
  Summary: Single File commands for Interactive python.
5
5
  Requires-Python: >=3.8
6
6
  Requires-Dist: tomli>=2.4.0; python_version < '3.11'
@@ -1,179 +1,181 @@
1
- [build-system]
2
- build-backend = "hatchling.build"
3
- requires = ["hatchling"]
4
-
5
- [project]
6
- dependencies = ["tomli>=2.4.0; python_version<'3.11'"]
7
- description = "Single File commands for Interactive python."
8
- name = "pysfi"
9
- readme = "README.md"
10
- requires-python = ">=3.8"
11
- version = "0.1.14"
12
-
13
- [project.scripts]
14
- alarmclk = "sfi.alarmclock.alarmclock:main"
15
- bumpversion = "sfi.bumpversion.bumpversion:main"
16
- cleanbuild = "sfi.cleanbuild.cleanbuild:main"
17
- condasetup = "sfi.condasetup.condasetup:main"
18
- docdiff = "sfi.docdiff.docdiff:main"
19
- docscan = "sfi.docscan.docscan:main"
20
- docscan-gui = "sfi.docscan.docscan_gui:main"
21
- filedate = "sfi.filedate.filedate:main"
22
- gitt = "sfi.gittool.gittool:main"
23
- img2pdf = "sfi.img2pdf.img2pdf:main"
24
- llmcli = "sfi.llmclient.llmclient:main"
25
- llmqnt = "sfi.llmquantize.llmquantize:main"
26
- llmsvr = "sfi.llmserver.llmserver:main"
27
- mkp = "sfi.makepython.makepython:main"
28
- makepython = "sfi.makepython.makepython:main"
29
- pdfsplit = "sfi.pdfsplit.pdfsplit:main"
30
- pyarchive = "sfi.pyarchive.pyarchive:main"
31
- pyembedinstall = "sfi.pyembedinstall.pyembedinstall:main"
32
- pylibpack = "sfi.pylibpack.pylibpack:main"
33
- pyloadergen = "sfi.pyloadergen.pyloadergen:main"
34
- pyp = "sfi.pypack.pypack:main"
35
- pypack = "sfi.pypack.pypack:main"
36
- pypp = "sfi.pyprojectparse.pyprojectparse:main"
37
- pyprojectparse = "sfi.pyprojectparse.pyprojectparse:main"
38
- pysourcepack = "sfi.pysourcepack.pysourcepack:main"
39
- quizbase = "sfi.quizbase.quizbase:main"
40
- quizbase-gui = "sfi.quizbase.quizbase_gui:main"
41
- regval = "sfi.regexvalidate.regexvalidate:main"
42
- sfi = "sfi.cli:main"
43
- taskk = "sfi.taskkill.taskkill:main"
44
- wch = "sfi.which.which:main"
45
-
46
- [project.optional-dependencies]
47
- all = ["pysfi[gui,office,ocr,extra]"]
48
- extra = ["ebooklib>=0.18", "markdown>=3.5", "odfpy>=1.4.1", "pypdf>=3.0.0"]
49
- gui = ["PySide2>=5.15.2.1", "pyside2-stubs>=5.15.2.1.2"]
50
- ocr = ["Pillow>=10.0.0", "pytesseract>=0.3.10"]
51
- office = [
52
- "openpyxl>=3.1.0",
53
- "pymupdf>=1.24.11",
54
- "python-docx>=1.1.0",
55
- "python-pptx>=0.6.21",
56
- "pywin32>=311; sys.platform=='win32'",
57
- ]
58
-
59
- [tool.hatch.build.targets.wheel]
60
- exclude = [
61
- "sfi/*/README.md",
62
- "sfi/*/dist",
63
- "sfi/*/pyproject.toml",
64
- "sfi/*/tests",
65
- ]
66
- packages = ["sfi"]
67
-
68
- # Only include necessary source files to minimize package size
69
- [tool.hatch.build]
70
- include = ["README.md", "sfi/**/*.py", "sfi/pyproject.toml"]
71
-
72
- [tool.ruff]
73
- line-length = 88
74
- target-version = "py38"
75
-
76
- # Exclude files and directories
77
- exclude = [
78
- ".bzr",
79
- ".direnv",
80
- ".eggs",
81
- ".git",
82
- ".git-rewrite",
83
- ".hg",
84
- ".mypy_cache",
85
- ".nox",
86
- ".pants.d",
87
- ".pytype",
88
- ".ruff_cache",
89
- ".svn",
90
- ".tox",
91
- ".venv",
92
- "__pypackages__",
93
- "_build",
94
- "buck-out",
95
- "build",
96
- "dist",
97
- "node_modules",
98
- "venv",
99
- ]
100
-
101
- [tool.ruff.lint]
102
- dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
103
- fixable = ["ALL"]
104
- ignore = [
105
- "B008", # Do not perform function calls in function arguments
106
- "E501", # Line too long (handled by formatter)
107
- "RUF001", # Language specific rules
108
- "RUF002", # Language specific rules
109
- "RUF003", # Language specific rules
110
- ]
111
- select = [
112
- "B", # flake8-bugbear
113
- "C4", # flake8-comprehensions
114
- "E", # pycodestyle errors
115
- "F", # Pyflakes
116
- "I", # isort
117
- "N", # pep8-naming
118
- "RUF", # Ruff-specific rules
119
- "SIM", # flake8-simplify
120
- "UP", # pyupgrade
121
- "W", # pycodestyle warnings
122
- ]
123
- unfixable = []
124
-
125
- [tool.ruff.lint.isort]
126
- known-first-party = ["sfi"]
127
-
128
- [tool.ruff.lint.per-file-ignores]
129
- "__init__.py" = ["F401"] # Allow unused imports
130
-
131
- [tool.uv.sources]
132
- pysfi = { workspace = true }
133
-
134
- [tool.uv.workspace]
135
- members = [
136
- "sfi/alarmclock",
137
- "sfi/bumpversion",
138
- "sfi/cleanbuild",
139
- "sfi/condasetup",
140
- "sfi/docdiff",
141
- "sfi/docscan",
142
- "sfi/filedate",
143
- "sfi/gittool",
144
- "sfi/img2pdf",
145
- "sfi/llmclient",
146
- "sfi/llmquantize",
147
- "sfi/llmserver",
148
- "sfi/makepython",
149
- "sfi/pdfsplit",
150
- "sfi/pyarchive",
151
- "sfi/pyembedinstall",
152
- "sfi/pylibpack",
153
- "sfi/pyloadergen",
154
- "sfi/pypack",
155
- "sfi/pyprojectparse",
156
- "sfi/pysourcepack",
157
- "sfi/quizbase",
158
- "sfi/regexvalidate",
159
- "sfi/taskkill",
160
- "sfi/which",
161
- ]
162
-
163
- [dependency-groups]
164
- dev = [
165
- "hatch>=1.14.2",
166
- "hypothesis>=6.113.0",
167
- "pysfi[all]",
168
- "pyside2>=5.15.2.1",
169
- "pytest-asyncio>=0.24.0",
170
- "pytest-benchmark>=4.0.0",
171
- "pytest-cov>=5.0.0",
172
- "pytest-mock>=3.14.0",
173
- "pytest-qt>=4.4.0",
174
- "pytest-xdist>=3.5.0",
175
- "pytest>=8.3.5",
176
- "qdarkstyle>=3.2.3",
177
- "ruff>=0.14.11",
178
- "tomli>=2.4.0",
179
- ]
1
+ [build-system]
2
+ build-backend = "hatchling.build"
3
+ requires = ["hatchling"]
4
+
5
+ [project]
6
+ dependencies = ["tomli>=2.4.0; python_version<'3.11'"]
7
+ description = "Single File commands for Interactive python."
8
+ name = "pysfi"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ version = "0.1.15"
12
+
13
+ [project.scripts]
14
+ alarmclk = "sfi.alarmclock.alarmclock:main"
15
+ bumpversion = "sfi.bumpversion.bumpversion:main"
16
+ cleanbuild = "sfi.cleanbuild.cleanbuild:main"
17
+ condasetup = "sfi.condasetup.condasetup:main"
18
+ docdiff = "sfi.docdiff.docdiff:main"
19
+ docscan = "sfi.docscan.docscan:main"
20
+ docscan-gui = "sfi.docscan.docscan_gui:main"
21
+ filedate = "sfi.filedate.filedate:main"
22
+ gitt = "sfi.gittool.gittool:main"
23
+ img2pdf = "sfi.img2pdf.img2pdf:main"
24
+ llmcli = "sfi.llmclient.llmclient:main"
25
+ llmqnt = "sfi.llmquantize.llmquantize:main"
26
+ llmsvr = "sfi.llmserver.llmserver:main"
27
+ makepython = "sfi.makepython.makepython:main"
28
+ mkp = "sfi.makepython.makepython:main"
29
+ pdfcrypt = "sfi.pdfcrypt.pdfcrypt:main"
30
+ pdfsplit = "sfi.pdfsplit.pdfsplit:main"
31
+ pyarchive = "sfi.pyarchive.pyarchive:main"
32
+ pyembedinstall = "sfi.pyembedinstall.pyembedinstall:main"
33
+ pylibpack = "sfi.pylibpack.pylibpack:main"
34
+ pyloadergen = "sfi.pyloadergen.pyloadergen:main"
35
+ pyp = "sfi.pypack.pypack:main"
36
+ pypack = "sfi.pypack.pypack:main"
37
+ pypp = "sfi.pyprojectparse.pyprojectparse:main"
38
+ pyprojectparse = "sfi.pyprojectparse.pyprojectparse:main"
39
+ pysourcepack = "sfi.pysourcepack.pysourcepack:main"
40
+ quizbase = "sfi.quizbase.quizbase:main"
41
+ quizbase-gui = "sfi.quizbase.quizbase_gui:main"
42
+ regval = "sfi.regexvalidate.regexvalidate:main"
43
+ sfi = "sfi.cli:main"
44
+ taskk = "sfi.taskkill.taskkill:main"
45
+ wch = "sfi.which.which:main"
46
+
47
+ [project.optional-dependencies]
48
+ all = ["pysfi[gui,office,ocr,extra]"]
49
+ extra = ["ebooklib>=0.18", "markdown>=3.5", "odfpy>=1.4.1", "pypdf>=3.0.0"]
50
+ gui = ["PySide2>=5.15.2.1", "pyside2-stubs>=5.15.2.1.2"]
51
+ ocr = ["Pillow>=10.0.0", "pytesseract>=0.3.10"]
52
+ office = [
53
+ "openpyxl>=3.1.0",
54
+ "pymupdf>=1.24.11",
55
+ "python-docx>=1.1.0",
56
+ "python-pptx>=0.6.21",
57
+ "pywin32>=311; sys.platform=='win32'",
58
+ ]
59
+
60
+ [tool.hatch.build.targets.wheel]
61
+ exclude = [
62
+ "sfi/*/README.md",
63
+ "sfi/*/dist",
64
+ "sfi/*/pyproject.toml",
65
+ "sfi/*/tests",
66
+ ]
67
+ packages = ["sfi"]
68
+
69
+ # Only include necessary source files to minimize package size
70
+ [tool.hatch.build]
71
+ include = ["README.md", "sfi/**/*.py", "sfi/pyproject.toml"]
72
+
73
+ [tool.ruff]
74
+ line-length = 88
75
+ target-version = "py38"
76
+
77
+ # Exclude files and directories
78
+ exclude = [
79
+ ".bzr",
80
+ ".direnv",
81
+ ".eggs",
82
+ ".git",
83
+ ".git-rewrite",
84
+ ".hg",
85
+ ".mypy_cache",
86
+ ".nox",
87
+ ".pants.d",
88
+ ".pytype",
89
+ ".ruff_cache",
90
+ ".svn",
91
+ ".tox",
92
+ ".venv",
93
+ "__pypackages__",
94
+ "_build",
95
+ "buck-out",
96
+ "build",
97
+ "dist",
98
+ "node_modules",
99
+ "venv",
100
+ ]
101
+
102
+ [tool.ruff.lint]
103
+ dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
104
+ fixable = ["ALL"]
105
+ ignore = [
106
+ "B008", # Do not perform function calls in function arguments
107
+ "E501", # Line too long (handled by formatter)
108
+ "RUF001", # Language specific rules
109
+ "RUF002", # Language specific rules
110
+ "RUF003", # Language specific rules
111
+ ]
112
+ select = [
113
+ "B", # flake8-bugbear
114
+ "C4", # flake8-comprehensions
115
+ "E", # pycodestyle errors
116
+ "F", # Pyflakes
117
+ "I", # isort
118
+ "N", # pep8-naming
119
+ "RUF", # Ruff-specific rules
120
+ "SIM", # flake8-simplify
121
+ "UP", # pyupgrade
122
+ "W", # pycodestyle warnings
123
+ ]
124
+ unfixable = []
125
+
126
+ [tool.ruff.lint.isort]
127
+ known-first-party = ["sfi"]
128
+
129
+ [tool.ruff.lint.per-file-ignores]
130
+ "__init__.py" = ["F401"] # Allow unused imports
131
+
132
+ [tool.uv.sources]
133
+ pysfi = { workspace = true }
134
+
135
+ [tool.uv.workspace]
136
+ members = [
137
+ "sfi/alarmclock",
138
+ "sfi/bumpversion",
139
+ "sfi/cleanbuild",
140
+ "sfi/condasetup",
141
+ "sfi/docdiff",
142
+ "sfi/docscan",
143
+ "sfi/filedate",
144
+ "sfi/gittool",
145
+ "sfi/img2pdf",
146
+ "sfi/llmclient",
147
+ "sfi/llmquantize",
148
+ "sfi/llmserver",
149
+ "sfi/makepython",
150
+ "sfi/pdfcrypt",
151
+ "sfi/pdfsplit",
152
+ "sfi/pyarchive",
153
+ "sfi/pyembedinstall",
154
+ "sfi/pylibpack",
155
+ "sfi/pyloadergen",
156
+ "sfi/pypack",
157
+ "sfi/pyprojectparse",
158
+ "sfi/pysourcepack",
159
+ "sfi/quizbase",
160
+ "sfi/regexvalidate",
161
+ "sfi/taskkill",
162
+ "sfi/which",
163
+ ]
164
+
165
+ [dependency-groups]
166
+ dev = [
167
+ "hatch>=1.14.2",
168
+ "hypothesis>=6.113.0",
169
+ "pysfi[all]",
170
+ "pyside2>=5.15.2.1",
171
+ "pytest-asyncio>=0.24.0",
172
+ "pytest-benchmark>=4.0.0",
173
+ "pytest-cov>=5.0.0",
174
+ "pytest-mock>=3.14.0",
175
+ "pytest-qt>=4.4.0",
176
+ "pytest-xdist>=3.5.0",
177
+ "pytest>=8.3.5",
178
+ "qdarkstyle>=3.2.3",
179
+ "ruff>=0.14.11",
180
+ "tomli>=2.4.0",
181
+ ]
@@ -16,5 +16,5 @@ or imported as a Python library.
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- __version__ = "0.1.14"
19
+ __version__ = "0.1.15"
20
20
  __all__ = ["__version__"]
@@ -0,0 +1 @@
1
+ """Tests for alarmclock module."""
@@ -0,0 +1,113 @@
1
+ """Core tests for alarmclock module (non-GUI tests)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import pytest
6
+
7
+ from sfi.alarmclock.alarmclock import AlarmClockConfig
8
+
9
+
10
+ class TestAlarmClockConfig:
11
+ """Tests for AlarmClockConfig dataclass."""
12
+
13
+ def test_default_config_initialization(self):
14
+ """Test default configuration initialization."""
15
+ config = AlarmClockConfig()
16
+
17
+ # Test default values
18
+ assert config.ALARM_CLOCK_TITLE == "Digital Alarm Clock"
19
+ assert config.DIGITAL_FONT == "bold italic 81px 'Consolas'"
20
+ assert config.DIGITAL_COLOR == "#ccee00"
21
+ assert config.DIGITAL_BORDER_COLORS == (
22
+ "#00aa00",
23
+ "#eecc00",
24
+ "#aa00aa",
25
+ "#c0e0b0",
26
+ )
27
+ assert config.DIGITAL_TIMER_FORMAT == "%H:%M:%S"
28
+ assert config.DIGITAL_UPDATE_INTERVAL == 1000
29
+ assert config.BLINK_TITLE == "Alarm Reminder!"
30
+ assert config.BLINK_CONTENT == "⏰ Time's Up!"
31
+ assert config.BLINK_TYPE == "color"
32
+ assert config.BLINK_BG_COLORS == (
33
+ "#baf1ba",
34
+ "#f8ccc3",
35
+ "#aab4f0",
36
+ "#efaec0",
37
+ )
38
+ assert config.BLINK_INTERVAL == 300
39
+ assert config.DELAY_STEPS == (1, 5, 10, 15, 30, 60)
40
+
41
+ def test_config_modification(self):
42
+ """Test that configuration can be modified."""
43
+ # Since AlarmClockConfig is frozen, we need to create a new instance
44
+ # with different values, but the current implementation doesn't support this
45
+ # Let's test that we can access all the configuration attributes
46
+ config = AlarmClockConfig()
47
+
48
+ # Just verify all attributes exist and have expected types
49
+ assert isinstance(config.ALARM_CLOCK_TITLE, str)
50
+ assert isinstance(config.DIGITAL_FONT, str)
51
+ assert isinstance(config.DIGITAL_COLOR, str)
52
+ assert isinstance(config.DIGITAL_BORDER_COLORS, tuple)
53
+ assert isinstance(config.DIGITAL_TIMER_FORMAT, str)
54
+ assert isinstance(config.DIGITAL_UPDATE_INTERVAL, int)
55
+ assert isinstance(config.BLINK_TITLE, str)
56
+ assert isinstance(config.BLINK_CONTENT, str)
57
+ assert isinstance(config.BLINK_TYPE, str)
58
+ assert isinstance(config.BLINK_BG_COLORS, tuple)
59
+ assert isinstance(config.BLINK_INTERVAL, int)
60
+ assert isinstance(config.DELAY_STEPS, tuple)
61
+
62
+
63
+ class TestAlarmClockFunctionality:
64
+ """Tests for alarm clock core functionality."""
65
+
66
+ def test_digital_clock_time_format(self):
67
+ """Test digital clock time formatting."""
68
+ from datetime import datetime, timedelta, timezone
69
+
70
+ # Test time formatting
71
+ test_time = datetime.now(timezone.utc) + timedelta(hours=8)
72
+ formatted_time = test_time.strftime("%H:%M:%S")
73
+
74
+ # Verify format
75
+ assert len(formatted_time) == 8 # HH:MM:SS
76
+ assert formatted_time[2] == ":" # Hour-minute separator
77
+ assert formatted_time[5] == ":" # Minute-second separator
78
+
79
+ def test_delay_steps_calculation(self):
80
+ """Test delay steps calculation."""
81
+ config = AlarmClockConfig()
82
+
83
+ # Verify delay steps are reasonable
84
+ assert len(config.DELAY_STEPS) == 6
85
+ assert all(isinstance(step, int) for step in config.DELAY_STEPS)
86
+ assert all(step > 0 for step in config.DELAY_STEPS)
87
+ assert config.DELAY_STEPS == (1, 5, 10, 15, 30, 60)
88
+
89
+ def test_blink_colors_validation(self):
90
+ """Test blink colors are valid."""
91
+ config = AlarmClockConfig()
92
+
93
+ # Verify blink colors are valid hex colors
94
+ for color in config.BLINK_BG_COLORS:
95
+ assert color.startswith("#")
96
+ assert len(color) == 7 # #RRGGBB format
97
+ assert all(c.lower() in "0123456789abcdef" for c in color[1:])
98
+
99
+ def test_digital_colors_validation(self):
100
+ """Test digital clock colors are valid."""
101
+ config = AlarmClockConfig()
102
+
103
+ # Verify digital colors are valid
104
+ assert config.DIGITAL_COLOR.startswith("#")
105
+ assert len(config.DIGITAL_COLOR) == 7
106
+
107
+ for color in config.DIGITAL_BORDER_COLORS:
108
+ assert color.startswith("#")
109
+ assert len(color) == 7
110
+
111
+
112
+ if __name__ == "__main__":
113
+ pytest.main([__file__, "-v"])