pysfi 0.1.12__tar.gz → 0.1.14__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.
- {pysfi-0.1.12 → pysfi-0.1.14}/PKG-INFO +1 -1
- {pysfi-0.1.12 → pysfi-0.1.14}/pyproject.toml +179 -172
- pysfi-0.1.14/sfi/__init__.py +20 -0
- pysfi-0.1.14/sfi/alarmclock/README.md +117 -0
- pysfi-0.1.14/sfi/alarmclock/__init__.py +3 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/alarmclock/alarmclock.py +23 -40
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/bumpversion/__init__.py +3 -1
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/bumpversion/bumpversion.py +64 -15
- pysfi-0.1.14/sfi/cleanbuild/__init__.py +3 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/cleanbuild/cleanbuild.py +5 -1
- pysfi-0.1.14/sfi/cli.py +32 -0
- pysfi-0.1.14/sfi/condasetup/__init__.py +1 -0
- pysfi-0.1.14/sfi/condasetup/condasetup.py +131 -0
- pysfi-0.1.14/sfi/docdiff/__init__.py +1 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/docdiff/docdiff.py +3 -2
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/docscan/__init__.py +1 -1
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/docscan/docscan.py +78 -23
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/docscan/docscan_gui.py +152 -48
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/filedate/filedate.py +12 -5
- pysfi-0.1.14/sfi/filedate/tests/__init__.py +1 -0
- pysfi-0.1.14/sfi/img2pdf/img2pdf.py +453 -0
- pysfi-0.1.14/sfi/img2pdf/tests/test_benchmark.py +88 -0
- pysfi-0.1.14/sfi/img2pdf/tests/test_img2pdf.py +435 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/llmclient/llmclient.py +31 -8
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/llmquantize/llmquantize.py +76 -37
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/llmquantize/tests/test_llmquantize.py +0 -30
- pysfi-0.1.14/sfi/llmserver/__init__.py +1 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/llmserver/llmserver.py +63 -13
- pysfi-0.1.14/sfi/makepython/README.md +188 -0
- pysfi-0.1.14/sfi/makepython/makepython.py +1271 -0
- pysfi-0.1.14/sfi/makepython/tests/test_benchmark.py +289 -0
- pysfi-0.1.14/sfi/makepython/tests/test_makepython.py +320 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/pdfsplit/pdfsplit.py +45 -12
- pysfi-0.1.14/sfi/pyarchive/README.md +270 -0
- pysfi-0.1.14/sfi/pyarchive/__init__.py +1 -0
- pysfi-0.1.14/sfi/pyarchive/pyarchive.py +1048 -0
- pysfi-0.1.14/sfi/pyarchive/tests/__init__.py +1 -0
- pysfi-0.1.14/sfi/pyarchive/tests/test_benchmark.py +444 -0
- pysfi-0.1.14/sfi/pyarchive/tests/test_pyarchive.py +245 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/pyembedinstall/pyembedinstall.py +88 -89
- pysfi-0.1.14/sfi/pyembedinstall/tests/__init__.py +1 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/pyembedinstall/tests/test_pyembedinstall.py +846 -413
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/pylibpack/pylibpack.py +561 -463
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/pylibpack/tests/test_benchmark.py +51 -20
- pysfi-0.1.14/sfi/pylibpack/tests/test_pylibpack.py +1508 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/pyloadergen/pyloadergen.py +372 -218
- pysfi-0.1.14/sfi/pyloadergen/tests/test_benchmark.py +67 -0
- pysfi-0.1.14/sfi/pyloadergen/tests/test_pyloadergen.py +1048 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/pypack/README.md +11 -0
- pysfi-0.1.14/sfi/pypack/pypack.py +693 -0
- pysfi-0.1.14/sfi/pypack/tests/test_benchmark.py +106 -0
- pysfi-0.1.14/sfi/pypack/tests/test_pack.py +145 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/pyprojectparse/pyprojectparse.py +337 -40
- pysfi-0.1.14/sfi/pyprojectparse/tests/__init__.py +1 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/pyprojectparse/tests/test_benchmark.py +13 -13
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/pyprojectparse/tests/test_projectparse.py +211 -9
- pysfi-0.1.14/sfi/pysourcepack/__init__.py +1 -0
- pysfi-0.1.14/sfi/pysourcepack/pysourcepack.py +387 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/quizbase/quizbase_gui.py +2 -2
- pysfi-0.1.14/sfi/taskkill/README.md +198 -0
- pysfi-0.1.14/sfi/taskkill/taskkill.py +343 -0
- pysfi-0.1.14/sfi/taskkill/tests/__init__.py +1 -0
- pysfi-0.1.14/sfi/taskkill/tests/test_benchmark.py +232 -0
- pysfi-0.1.14/sfi/taskkill/tests/test_smoke.py +41 -0
- pysfi-0.1.14/sfi/taskkill/tests/test_taskkill.py +339 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/which/which.py +11 -3
- pysfi-0.1.12/sfi/__init__.py +0 -3
- pysfi-0.1.12/sfi/alarmclock/README.md +0 -64
- pysfi-0.1.12/sfi/cli.py +0 -11
- pysfi-0.1.12/sfi/condasetup/condasetup.py +0 -116
- pysfi-0.1.12/sfi/makepython/makepython.py +0 -327
- pysfi-0.1.12/sfi/pyarchive/pyarchive.py +0 -418
- pysfi-0.1.12/sfi/pylibpack/tests/test_pylibpack.py +0 -774
- pysfi-0.1.12/sfi/pyloadergen/tests/test_benchmark.py +0 -235
- pysfi-0.1.12/sfi/pyloadergen/tests/test_pyloadergen.py +0 -325
- pysfi-0.1.12/sfi/pypack/pypack.py +0 -1142
- pysfi-0.1.12/sfi/pypack/tests/test_pack.py +0 -124
- pysfi-0.1.12/sfi/pysourcepack/pysourcepack.py +0 -308
- pysfi-0.1.12/sfi/taskkill/taskkill.py +0 -234
- pysfi-0.1.12/sfi/workflowengine/tests/__init__.py +0 -1
- pysfi-0.1.12/sfi/workflowengine/tests/test_benchmark.py +0 -725
- pysfi-0.1.12/sfi/workflowengine/tests/test_workflowengine.py +0 -740
- pysfi-0.1.12/sfi/workflowengine/workflowengine.py +0 -444
- {pysfi-0.1.12 → pysfi-0.1.14}/.gitignore +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/README.md +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/examples/pack_demo/README.md +0 -0
- {pysfi-0.1.12/sfi/cleanbuild → pysfi-0.1.14/examples/workflowengine}/README.md +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/bumpversion/README.md +0 -0
- {pysfi-0.1.12/sfi/alarmclock → pysfi-0.1.14/sfi/bumpversion/tests}/__init__.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/bumpversion/tests/test_bumpversion.py +0 -0
- {pysfi-0.1.12/sfi/condasetup → pysfi-0.1.14/sfi/cleanbuild}/README.md +0 -0
- {pysfi-0.1.12/sfi/gittool → pysfi-0.1.14/sfi/condasetup}/README.md +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/docdiff/README.md +0 -0
- {pysfi-0.1.12/sfi/bumpversion → pysfi-0.1.14/sfi/docdiff}/tests/__init__.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/docdiff/tests/test_benchmark.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/docdiff/tests/test_docdiff.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/docdiff/tests/test_enhanced.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/docdiff/tests/test_functional.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/docscan/README.md +0 -0
- {pysfi-0.1.12/sfi/docdiff/tests → pysfi-0.1.14/sfi/docscan/lang}/__init__.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/docscan/lang/eng.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/docscan/lang/zhcn.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/docscan/tests/__init__.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/docscan/tests/test_benchmark.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/docscan/tests/test_docscan.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/docscan/tests/test_enhanced.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/filedate/README.md +0 -0
- {pysfi-0.1.12/sfi/docscan/lang → pysfi-0.1.14/sfi/filedate}/__init__.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/filedate/tests/test_filedate.py +0 -0
- {pysfi-0.1.12/sfi/llmclient → pysfi-0.1.14/sfi/gittool}/README.md +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/gittool/__init__.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/gittool/gittool.py +0 -0
- {pysfi-0.1.12/sfi/llmquantize → pysfi-0.1.14/sfi/img2pdf}/README.md +0 -0
- {pysfi-0.1.12/sfi/filedate → pysfi-0.1.14/sfi/img2pdf}/__init__.py +0 -0
- {pysfi-0.1.12/sfi/llmclient → pysfi-0.1.14/sfi/img2pdf/tests}/__init__.py +0 -0
- {pysfi-0.1.12/sfi/llmserver → pysfi-0.1.14/sfi/llmclient}/README.md +0 -0
- {pysfi-0.1.12/sfi/llmquantize → pysfi-0.1.14/sfi/llmclient}/__init__.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/llmclient/tests/__init__.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/llmclient/tests/test_benchmark.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/llmclient/tests/test_llmclient.py +0 -0
- {pysfi-0.1.12/sfi/pyarchive → pysfi-0.1.14/sfi/llmquantize}/README.md +0 -0
- {pysfi-0.1.12/sfi/makepython → pysfi-0.1.14/sfi/llmquantize}/__init__.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/llmquantize/tests/__init__.py +0 -0
- {pysfi-0.1.12/sfi/workflowengine → pysfi-0.1.14/sfi/llmserver}/README.md +0 -0
- {pysfi-0.1.12/sfi/pdfsplit → pysfi-0.1.14/sfi/makepython}/__init__.py +0 -0
- {pysfi-0.1.12/sfi/pdfsplit/tests → pysfi-0.1.14/sfi/pdfsplit}/__init__.py +0 -0
- {pysfi-0.1.12/sfi/pyembedinstall → pysfi-0.1.14/sfi/pdfsplit/tests}/__init__.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/pdfsplit/tests/test_pdfsplit.py +0 -0
- {pysfi-0.1.12/sfi/pylibpack → pysfi-0.1.14/sfi/pyembedinstall}/__init__.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/pylibpack/README.md +0 -0
- {pysfi-0.1.12/sfi/pylibpack/tests → pysfi-0.1.14/sfi/pylibpack}/__init__.py +0 -0
- {pysfi-0.1.12/sfi/pyloadergen → pysfi-0.1.14/sfi/pylibpack/tests}/__init__.py +0 -0
- {pysfi-0.1.12/sfi/pyloadergen/tests → pysfi-0.1.14/sfi/pyloadergen}/__init__.py +0 -0
- {pysfi-0.1.12/sfi/pypack → pysfi-0.1.14/sfi/pyloadergen/tests}/__init__.py +0 -0
- {pysfi-0.1.12/sfi/pypack/tests → pysfi-0.1.14/sfi/pypack}/__init__.py +0 -0
- {pysfi-0.1.12/sfi/pyprojectparse → pysfi-0.1.14/sfi/pypack/tests}/__init__.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/pyprojectparse/README.md +0 -0
- {pysfi-0.1.12/sfi/quizbase → pysfi-0.1.14/sfi/pyprojectparse}/__init__.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/pysourcepack/README.md +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/quizbase/README.md +0 -0
- {pysfi-0.1.12/sfi/regexvalidate → pysfi-0.1.14/sfi/quizbase}/__init__.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/quizbase/quizbase.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/quizbase/tests/__init__.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/quizbase/tests/test_quizbase.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/quizbase/tests/test_quizbase_gui.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/regexvalidate/README.md +0 -0
- {pysfi-0.1.12/sfi/taskkill → pysfi-0.1.14/sfi/regexvalidate}/__init__.py +0 -0
- {pysfi-0.1.12 → pysfi-0.1.14}/sfi/regexvalidate/regexvalidate.py +0 -0
- {pysfi-0.1.12/sfi/which → pysfi-0.1.14/sfi/taskkill}/__init__.py +0 -0
- {pysfi-0.1.12/sfi/workflowengine → pysfi-0.1.14/sfi/which}/__init__.py +0 -0
|
@@ -1,172 +1,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.
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"sfi/*/
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
[
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
[tool.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
".
|
|
79
|
-
".
|
|
80
|
-
".
|
|
81
|
-
".
|
|
82
|
-
".
|
|
83
|
-
".
|
|
84
|
-
".
|
|
85
|
-
".
|
|
86
|
-
".
|
|
87
|
-
".
|
|
88
|
-
".
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
"
|
|
106
|
-
"
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
"
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
"
|
|
113
|
-
"
|
|
114
|
-
"
|
|
115
|
-
"
|
|
116
|
-
"
|
|
117
|
-
"
|
|
118
|
-
"
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
[tool.ruff.lint.
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
[tool.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
"sfi/
|
|
137
|
-
"sfi/
|
|
138
|
-
"sfi/
|
|
139
|
-
"sfi/
|
|
140
|
-
"sfi/
|
|
141
|
-
"sfi/
|
|
142
|
-
"sfi/
|
|
143
|
-
"sfi/
|
|
144
|
-
"sfi/
|
|
145
|
-
"sfi/
|
|
146
|
-
"sfi/
|
|
147
|
-
"sfi/
|
|
148
|
-
"sfi/
|
|
149
|
-
"sfi/
|
|
150
|
-
"sfi/
|
|
151
|
-
"sfi/
|
|
152
|
-
"sfi/
|
|
153
|
-
"sfi/
|
|
154
|
-
"sfi/
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
"
|
|
160
|
-
"
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
"
|
|
166
|
-
"
|
|
167
|
-
"
|
|
168
|
-
"
|
|
169
|
-
"
|
|
170
|
-
"
|
|
171
|
-
"
|
|
172
|
-
|
|
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
|
+
]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Single File commands for Interactive python.
|
|
2
|
+
|
|
3
|
+
pysfi (Python Single File Interactive) is a collection of Python utility
|
|
4
|
+
tools designed to streamline development workflows and enhance productivity.
|
|
5
|
+
|
|
6
|
+
This package provides:
|
|
7
|
+
- Document processing utilities (docscan, docdiff, pdfsplit, img2pdf)
|
|
8
|
+
- Development tools (makepython, bumpversion, cleanbuild)
|
|
9
|
+
- System management utilities (filedate, taskkill, gittool)
|
|
10
|
+
- AI/LLM tools (llmclient, llmserver, llmquantize)
|
|
11
|
+
- And many more specialized utilities
|
|
12
|
+
|
|
13
|
+
Each module can be used independently as a command-line tool
|
|
14
|
+
or imported as a Python library.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
__version__ = "0.1.14"
|
|
20
|
+
__all__ = ["__version__"]
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Alarm Clock
|
|
2
|
+
|
|
3
|
+
A digital alarm clock application with a graphical user interface built using PySide2. Features include configurable alarms, digital time display, visual notifications, alarm history, and advanced configuration options.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Digital clock display** with animated border effects and customizable styling
|
|
8
|
+
- **Configurable alarm time setting** with precise time selection
|
|
9
|
+
- **Quick delay options** (1, 5, 10, 15, 30, 60 minutes) for fast alarm setup
|
|
10
|
+
- **Repeat alarm functionality** for daily recurring alarms
|
|
11
|
+
- **Snooze feature** with configurable snooze duration and count limits
|
|
12
|
+
- **Multiple visual notification effects** including color, opacity, and combined animations
|
|
13
|
+
|
|
14
|
+
- **Alarm history tracking** with statistics and recent activity
|
|
15
|
+
- **Dark theme interface** with modern styling
|
|
16
|
+
- **Persistent configuration** with automatic saving and loading
|
|
17
|
+
- **Advanced settings** including window behavior, logging, and performance options
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
Install the required dependencies:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install -e .
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
Run the alarm clock application:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
alarmclk
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Or directly with Python:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
python -m sfi.alarmclock
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Command Line Options
|
|
42
|
+
|
|
43
|
+
- `-d, --debug`: Enable debug mode with verbose logging
|
|
44
|
+
- `-v, --version`: Show version information
|
|
45
|
+
- `--config PATH`: Use custom configuration file
|
|
46
|
+
- `--reset-config`: Reset configuration to defaults
|
|
47
|
+
|
|
48
|
+
### Configuration
|
|
49
|
+
|
|
50
|
+
The application creates configuration files in `~/.pysfi/alarmclock/`:
|
|
51
|
+
|
|
52
|
+
- `config.json`: Main configuration settings
|
|
53
|
+
- `history.json`: Alarm history and statistics
|
|
54
|
+
- `alarmclock.log`: Application logs
|
|
55
|
+
|
|
56
|
+
Configuration can be customized through the config file or programmatically.
|
|
57
|
+
|
|
58
|
+
## Configuration Parameters
|
|
59
|
+
|
|
60
|
+
The application uses the following configuration parameters:
|
|
61
|
+
|
|
62
|
+
- **Digital Clock**: Displays current time with animated border colors
|
|
63
|
+
- **Alarm Time**: Set specific time for the alarm to trigger
|
|
64
|
+
- **Delay Options**: Quick buttons to set alarms for specific intervals
|
|
65
|
+
- **Repeat Option**: Enable/disable alarm repetition
|
|
66
|
+
- **Visual Notifications**: Alert dialog with blinking effect
|
|
67
|
+
|
|
68
|
+
## Architecture
|
|
69
|
+
|
|
70
|
+
The application follows a modular design:
|
|
71
|
+
|
|
72
|
+
- `AlarmClockConfig`: Configuration dataclass with all application settings
|
|
73
|
+
- `DigitalClock`: Widget displaying current time with animation
|
|
74
|
+
- `BlinkDialog`: Notification dialog with visual effects
|
|
75
|
+
- `AlarmClock`: Main application window with GUI controls
|
|
76
|
+
|
|
77
|
+
## Testing
|
|
78
|
+
|
|
79
|
+
The module includes comprehensive tests divided into two categories:
|
|
80
|
+
|
|
81
|
+
### Core Tests (Non-GUI)
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
python -m pytest sfi/alarmclock/tests/test_alarmclock_core.py -v
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Tests configuration, data classes, enums, and core logic without requiring a GUI environment.
|
|
88
|
+
|
|
89
|
+
### GUI Tests
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
python -m pytest sfi/alarmclock/tests/test_alarmclock_gui.py -v -m qt
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Tests GUI components using pytest-qt. These tests require a working Qt environment.
|
|
96
|
+
|
|
97
|
+
### Benchmark Tests
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
python -m pytest sfi/alarmclock/tests/test_benchmark.py -v
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Performance benchmarks for critical operations.
|
|
104
|
+
|
|
105
|
+
### Run All Tests
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
python -m pytest sfi/alarmclock/tests/ -v
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Dependencies
|
|
112
|
+
|
|
113
|
+
- PySide2: GUI framework
|
|
114
|
+
- qdarkstyle: Dark theme styling
|
|
115
|
+
- typing-extensions: Type hinting support for older Python versions
|
|
116
|
+
- pytest: Testing framework
|
|
117
|
+
- pytest-qt: Qt testing utilities
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import argparse
|
|
4
3
|
import logging
|
|
5
4
|
import random
|
|
6
5
|
import sys
|
|
@@ -8,7 +7,6 @@ from dataclasses import dataclass
|
|
|
8
7
|
from datetime import datetime, timedelta, timezone
|
|
9
8
|
from functools import partial
|
|
10
9
|
|
|
11
|
-
import qdarkstyle
|
|
12
10
|
from PySide2.QtCore import QSize, Qt, QTime, QTimer
|
|
13
11
|
from PySide2.QtGui import QCloseEvent
|
|
14
12
|
from PySide2.QtWidgets import (
|
|
@@ -28,7 +26,7 @@ __version__ = "0.1.3"
|
|
|
28
26
|
__build_date__ = "2026-01-22"
|
|
29
27
|
|
|
30
28
|
|
|
31
|
-
@dataclass
|
|
29
|
+
@dataclass
|
|
32
30
|
class AlarmClockConfig:
|
|
33
31
|
"""Configuration for the alarm clock application."""
|
|
34
32
|
|
|
@@ -87,9 +85,9 @@ class DigitalClock(QLabel):
|
|
|
87
85
|
logger.debug(f"Updated time: {current}")
|
|
88
86
|
|
|
89
87
|
# Add blink effect
|
|
90
|
-
self._color = random.choice(
|
|
91
|
-
|
|
92
|
-
)
|
|
88
|
+
self._color = random.choice([
|
|
89
|
+
c for c in config.DIGITAL_BORDER_COLORS if c != self._color
|
|
90
|
+
])
|
|
93
91
|
self.setStyleSheet(f"""
|
|
94
92
|
font: {config.DIGITAL_FONT};
|
|
95
93
|
color: {config.DIGITAL_COLOR};
|
|
@@ -112,6 +110,7 @@ class BlinkDialog(QDialog):
|
|
|
112
110
|
self.windowFlags() | Qt.WindowStaysOnTopHint | Qt.WindowType.Dialog,
|
|
113
111
|
)
|
|
114
112
|
self.setFixedSize(QSize(400, 240))
|
|
113
|
+
self.setWindowFlag(Qt.WindowCloseButtonHint, False)
|
|
115
114
|
|
|
116
115
|
layout = QVBoxLayout()
|
|
117
116
|
msg_label = QLabel(config.BLINK_CONTENT)
|
|
@@ -122,32 +121,28 @@ class BlinkDialog(QDialog):
|
|
|
122
121
|
msg_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
123
122
|
|
|
124
123
|
close_button = QPushButton("Close Alarm")
|
|
125
|
-
close_button.clicked.connect(self.
|
|
124
|
+
close_button.clicked.connect(self.close_alarm)
|
|
126
125
|
|
|
127
126
|
layout.addWidget(msg_label)
|
|
128
127
|
layout.addWidget(close_button)
|
|
129
128
|
self.setLayout(layout)
|
|
130
129
|
|
|
131
|
-
# Prevent user from closing dialog by other means, ensure button click only
|
|
132
|
-
self.setWindowFlag(Qt.WindowCloseButtonHint, False)
|
|
133
|
-
|
|
134
130
|
# Blink control variables and timer
|
|
135
131
|
self.blink_timer = QTimer(self)
|
|
136
132
|
self.blink_timer.timeout.connect(self.update_blink)
|
|
137
133
|
self.blink_state = False
|
|
138
134
|
self.blink_type = config.BLINK_TYPE
|
|
139
|
-
|
|
140
|
-
# Initialize style
|
|
141
135
|
self.bg_color = random.choice(config.BLINK_BG_COLORS)
|
|
142
|
-
self.origin_style = self.styleSheet()
|
|
143
136
|
self.blink_timer.start(config.BLINK_INTERVAL)
|
|
144
137
|
|
|
145
138
|
def update_blink(self) -> None:
|
|
146
139
|
"""Timer timeout, update blink state."""
|
|
147
140
|
if self.blink_type == "color":
|
|
148
141
|
# Color blink logic
|
|
149
|
-
colors = [
|
|
150
|
-
|
|
142
|
+
colors = [c for c in config.BLINK_BG_COLORS if c != self.bg_color]
|
|
143
|
+
new_color = random.choice(colors)
|
|
144
|
+
self.setStyleSheet(f"background-color: {new_color}")
|
|
145
|
+
self.bg_color = new_color
|
|
151
146
|
elif self.blink_type == "opacity":
|
|
152
147
|
# Opacity blink logic - Note: Some systems may not fully support window opacity
|
|
153
148
|
new_opacity = 0.3 if self.blink_state else 1.0
|
|
@@ -155,10 +150,14 @@ class BlinkDialog(QDialog):
|
|
|
155
150
|
|
|
156
151
|
self.blink_state = not self.blink_state # Toggle state
|
|
157
152
|
|
|
153
|
+
def close_alarm(self) -> None:
|
|
154
|
+
"""Close alarm dialog and stop blinking."""
|
|
155
|
+
self.stop_blinking()
|
|
156
|
+
self.accept()
|
|
157
|
+
|
|
158
158
|
def stop_blinking(self) -> None:
|
|
159
|
-
"""Stop blinking
|
|
159
|
+
"""Stop blinking."""
|
|
160
160
|
self.blink_timer.stop()
|
|
161
|
-
self.setStyleSheet(self.origin_style) # Restore original style
|
|
162
161
|
self.setWindowOpacity(1.0) # Ensure opacity is restored
|
|
163
162
|
|
|
164
163
|
def closeEvent(self, event: QCloseEvent) -> None: # noqa: N802
|
|
@@ -173,13 +172,6 @@ class AlarmClock(QMainWindow):
|
|
|
173
172
|
def __init__(self) -> None:
|
|
174
173
|
super().__init__()
|
|
175
174
|
self.setWindowTitle(f"{config.ALARM_CLOCK_TITLE} v{__version__}")
|
|
176
|
-
self.setGeometry(
|
|
177
|
-
QApplication.desktop().screenGeometry().center().x() - self.width() // 4,
|
|
178
|
-
QApplication.desktop().screenGeometry().center().y() - self.height() // 2,
|
|
179
|
-
self.width(),
|
|
180
|
-
self.height(),
|
|
181
|
-
)
|
|
182
|
-
self.adjustSize()
|
|
183
175
|
|
|
184
176
|
# Set window style
|
|
185
177
|
self.setStyleSheet("""
|
|
@@ -277,6 +269,13 @@ class AlarmClock(QMainWindow):
|
|
|
277
269
|
self.status_label.setStyleSheet("color: #aaaaaa; font-size: 16px;")
|
|
278
270
|
main_layout.addWidget(self.status_label)
|
|
279
271
|
|
|
272
|
+
# Center window on screen
|
|
273
|
+
self.adjustSize()
|
|
274
|
+
screen = QApplication.desktop().screenGeometry()
|
|
275
|
+
x = (screen.width() - self.width()) // 2
|
|
276
|
+
y = (screen.height() - self.height()) // 2
|
|
277
|
+
self.move(x, y)
|
|
278
|
+
|
|
280
279
|
# Alarm timer
|
|
281
280
|
self.alarm_timer = QTimer()
|
|
282
281
|
self.alarm_timer.timeout.connect(self.check_alarm)
|
|
@@ -330,11 +329,6 @@ class AlarmClock(QMainWindow):
|
|
|
330
329
|
dialog.exec_()
|
|
331
330
|
|
|
332
331
|
self.status_label.setText("⏰ Alarm Rang! ⏰")
|
|
333
|
-
self.status_label.setStyleSheet(
|
|
334
|
-
"color: #ff5555; font-size: 18px; font-weight: bold;",
|
|
335
|
-
)
|
|
336
|
-
|
|
337
|
-
# Add blink effect
|
|
338
332
|
self.status_label.setStyleSheet("""
|
|
339
333
|
color: #ff0000;
|
|
340
334
|
font-size: 18px;
|
|
@@ -350,18 +344,7 @@ class AlarmClock(QMainWindow):
|
|
|
350
344
|
|
|
351
345
|
|
|
352
346
|
def main() -> None:
|
|
353
|
-
parser = argparse.ArgumentParser(
|
|
354
|
-
prog="alarmclock", description="Digital Alarm Clock"
|
|
355
|
-
)
|
|
356
|
-
parser.add_argument("-d", "--debug", action="store_true", help="Enable debug mode")
|
|
357
|
-
parser.add_argument("-v", "--version", action="version", version=f"{__version__}")
|
|
358
|
-
|
|
359
|
-
args = parser.parse_args()
|
|
360
|
-
if args.debug:
|
|
361
|
-
logger.setLevel(logging.DEBUG)
|
|
362
|
-
|
|
363
347
|
app = QApplication(sys.argv)
|
|
364
|
-
app.setStyleSheet(qdarkstyle.load_stylesheet_pyside2())
|
|
365
348
|
window = AlarmClock()
|
|
366
349
|
window.show()
|
|
367
350
|
sys.exit(app.exec_())
|